2010-09-29 8 views
9

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

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

Есть ли способ, чтобы дать этому TransactionManager зимовать с конфигурацией, как

<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 собственности. Кстати, у меня действительно есть две разные серверные реализации.

EDIT: без конфигурации менеджера транзакций, 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 

ответ

1

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

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

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

ОК, спасибо, я полагаю, что правильный андерсор должен был открыть ошибку для Hibernate, так как это конфигурация на их стороне, которая виновата. – mleduque

0

Я недавно делал некоторые вещи с 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> 
+0

Ну, вы не можете сделать то же самое с JTA. – mleduque

5

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

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

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

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

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

Вторая точка является, пожалуй, то, что вы» вы пропустили?

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

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

+0

Да, требуется JTA. Интересно, почему люди всегда предполагают, что можно ответить на вопрос, опуская один из элементов. Для «lookup_class» и «factory_class» я не пропустил эту часть, но я * должен * не зависеть от используемого контейнера JEE, приложение должно быть развернуто (по крайней мере) на двух разных серверах приложений. – mleduque

+0

@mleduque люди с более широким взглядом на технологии принимают некоторые вещи из-за своего опыта. Например, я редко видел приложение Spring с JTA, в то время как я видел много случаев, когда люди бросались в него, фактически не нуждаясь в этом. Остальная часть вашего комментария - см. Мое обновление. – Bozho

+0

Почему кто-то использует слой Spring TM ... он не делает ничего своего только другого слоя с разными именами методов и не добавляет новых или более функциональных возможностей в JTA. В конце концов, он собирается выполнить поиск в jndi (если использовать JTA impl), который заканчивается той же проблемой магических строк и синглетов. –

Смежные вопросы