Как использовать стандартный поставщик сохраняемости WAS в Spring

Я разрабатываю портлет, который работает на сервере приложений WebSphere ( - я принимаю ту же проблему, если она была сервлетом, а не портлетом). На данный момент это зависит от Hibernate. Поскольку WAS предоставляет саму реализацию JPA, которая является модифицированной версией OpenJPA 2.0, я хочу избавиться от Hibernate.

Это моя установка. persistence.xml:

  <?xml version="1.0" encoding="UTF-8"?>
  <persistence xmlns="http://java.sun.com/xml/ns/persistence"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
               xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
  >
      <persistence-unit name="default" transaction-type="JTA">
          <provider>org.hibernate.ejb.HibernatePersistence</provider>

          <jta-data-source>jdbc/myDb</jta-data-source>
          <properties>
              <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform" />
              <property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect" />
          </properties>
      </persistence-unit>
  </persistence>

myPortlet-portlet.xml

  <!-- ... -->

  <tx:jta-transaction-manager />
  <jee:jndi-lookup jndi-name="jdbc/myDb" cache="true" id="dataSource" expected-type="javax.sql.DataSource" />

  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="persistenceUnitName" value="default" />
  </bean>

В моих DAO-классах я обращаюсь к entityManager с помощью аннотаций:

  @PersistenceContext(unitName = "default")
  private EntityManager entityManager;

Все работает нормально, используя Hibernate.

Согласно документам WebSphere Application Server, поставщик постоянства по умолчанию используется, если вы не укажете его с помощью <provider/>-tag в постоянстве.xml. Но после комментирования спецификации провайдера Spring выдает исключение из-за невозможности найти класс провайдера:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in PortletContext resource [/WEB-INF/myPortlet-portlet.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No PersistenceProvider specified in EntityManagerFactory configuration, and chosen PersistenceUnitInfo does not specify a provider class name either

Как я могу использовать предоставленную реализацию JPA вместе с Spring (Portlet) MVC?

2 ответа

Решение

Короткий ответ

Нельзя использовать поставщика по умолчанию в WebSphere, опуская поставщика, если вы хотите использовать LocalContainerEntityManagerFactoryBean.

Длинный ответ

Обычно менеджер сущностей создается фабрикой менеджеров сущностей, предоставляемой контейнером. Вы получаете его, выполняя контекстную петлю (EntityManager em = (EntityManager) ctx.lookup(...)) вручную или используйте функцию jndi-lookup Springs:

<beans>
    <jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/>
</beans>

В этом вопросе используется другой подход, LocalContainerEntityManagerFactoryBean, который создает саму фабрику менеджера сущностей. Эта фабрика диспетчера сущностей является прокси-сервером, который реализует все интерфейсы фабрики диспетчера сущностей. Для создания такого прокси Spring должен знать класс собственной фабрики диспетчера сущностей. Spring использует три разных способа определения класса:

  1. Обнаружить это по <provider/>-вход в постоянство.xml
  2. Запрос jpaVendorAdapter (указанный в одноименном свойстве фабричного компонента)
  3. Использование entityManagerFactoryInterface-свойство фабричного компонента

И именно поэтому вы не можете полностью опустить спецификацию вашего провайдера.

Скорее всего, это происходит потому, что Spring JAR, который вы включаете в свое приложение, содержит другую реализацию Persistence класс или другие классы JPA, используемые для "начальной загрузки" JPA.

Если вы хотите использовать поставщика WebSphere по умолчанию (или, точнее, использовать тот, который предоставляет JPA, сконфигурированный через экраны администрирования WebSphere), то вы должны убедиться, что код "начальной загрузки" JPA, вызываемый во время выполнения, принадлежит WebSphere, а не вам.

Вы должны искать JAR-дистрибутив Spring, который не связывается с JPA.

Другие вопросы по тегам