Использование Spring, определенногоactionManager в JPA / Hibernate - PullRequest
10 голосов
/ 29 сентября 2010

Предположим, вы используете JPA с Spring, с Hibernate в качестве реализации JPA.Режим транзакции JPA - это «JTA», поэтому вам нужно передать контейнер TransactionsManager в Hibernate.Классический ответ состоит в том, чтобы установить hibernate.transaction.manager_lookup_class в соответствующий класс для вашего сервера.

Однако, мне кажется, стыдно иметь это в зависимости от конкретной конфигурации сервера, так как вы уже нашли транзакциюManager в Spring с <tx:jta-transaction-manager>.

Есть ли способ передать этот TransactionManager Hibernate с такой конфигурацией, как

 <bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="persistenceUnitName" value="persistence_unit_name"/>
  <property name="jpaVendorAdapter">
   <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
  </property>
  <property name="jpaProperties">
   <props>
    <prop key="hibernate.transaction.manager_lookup_class">
     org.hibernate.transaction.SunONETransactionManagerLookup
    </prop>
   </props>
  </property>
 </bean>

 <tx:jta-transaction-manager/>

Цель - избавиться от свойства org.hibernate.transaction.SunONETransactionManagerLookup.Кстати, я действительно имею в виду две разные реализации сервера.

РЕДАКТИРОВАТЬ: без конфигурации диспетчера транзакций Hibernate дросселирует при создании EntityManagerFactory:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in URL [file:/C:/configuration/afoCuad-metier-ear/entitymanager-base-context.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: fr.tm.ima.cuad-afoCuad-metier-ejb-PU] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:529)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:495)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:656)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:629)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:147)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:338)
... 80 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: fr.tm.ima.cuad-afoCuad-metier-ejb-PU] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:901)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:308)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
... 93 more
Caused by: org.hibernate.HibernateException: The chosen transaction strategy requires access to the JTA TransactionManager
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:401)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:892)
... 98 more

Ответы [ 3 ]

5 голосов
/ 10 декабря 2010

Прежде всего - вам действительно нужен JTA?Обычно весна + спящий режим не требуют этого.Вы можете использовать простой JpaTransactionManager / HibernateTransactionManager.

Если вы действительно хотите JTA, то вам нужен JTA-провайдер.Если не работает на сервере приложений, проверьте этот вопрос , как использовать JTA в контейнере сервлета.(Также взгляните на этот вопрос )

Наконец, hibernate docs указывает, что для транзакций, управляемых контейнером:

Декларативныйразграничение транзакций является стандартной функцией EJB, также известной как транзакции, управляемые контейнером (CMT).В EJB 2.x вы будете использовать дескрипторы развертывания XML для создания сборки транзакции.В EJB 3.x вы можете использовать метаданные JDK 5.0 непосредственно в своем исходном коде, гораздо менее подробный подход.Чтобы включить разграничение транзакций CMT для EJB в конфигурации Hibernate:

  • установите hibernate.transaction.manager_lookup_class в качестве стратегии поиска для вашего контейнера JEE
  • , установите hibernate.transaction.factory_class в org.hibernate.transaction.CMTTransactionFactory

Возможно, вы упустили второй момент?

В дополнение к этому (следующий раздел) в документации сказано, что если вы хотите декларативную транзакцию, гибернация - это не то, гдеВы должны посмотреть.Вам нужно создать перехватчик.Это именно то, что весной менеджеры транзакций.И это был бы мой выбор, учитывая ваш технологический стек (Spring).

Если вы не хотите полагаться на одного поставщика JTA, сделайте две сборки.Например, у maven есть «профили maven», которые позволяют создавать сборки для разных сред.

1 голос
/ 31 января 2011

К сожалению, если взглянуть на Hibernate API, как и на многие другие продукты JBoss, у них есть класс, который обычно называется Configuration и содержит большинство, если не все основные элементы конфигурации. К сожалению, они (JBoss), кажется, любят хранить «Strings» для параметров и класса для определения местоположения экземпляров. Почти всегда невозможно просто установить фактическую готовую готовую к работе настройку.

Я собираюсь попробовать что-то похожее на следующее по той же причине, о которой вы упомянули.

  • Создание реализации TransactionManagerLookup
  • включает установщик, который принимает TM и устанавливает локальную переменную потока + экземпляр.
  • передать имя TML внутри свойств, которые вы передаете в конфигурацию.
  • Когда ваш TML запускается, скопируйте локальную переменную потока в ваш экземпляр fie.d.
  • очистить локальный поток, как только все будет сделано.
0 голосов
/ 09 декабря 2010

Я недавно делал кое-что с JPA / Grails, и конфигурация, которую я использовал, была следующей:

Помогает ли это вообще?

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="dataSource" ref="dataSource"/>
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<bean id="entityManagerFactory" class="org.hibernate.ejb.EntityManagerFactoryImpl">
 <constructor-arg index="0" ref="sessionFactory"/>
 <constructor-arg index="1">
   <bean id="javax.persistence.spi.PersistenceUnitTransactionType.RESOURCE_LOCAL" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
 </constructor-arg>
 <constructor-arg index="2" value="true"/>
 <constructor-arg index="3"><null/></constructor-arg>
</bean>
...