java 在 JPA/Hibernate 中使用 Spring 定义的 transactionManager
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3820019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Spring defined transactionManager in JPA/Hibernate
提问by mleduque
Suppose you use JPA with Spring, with Hibernate as JPA implementation.
JPA transaction mode is "JTA", so you need to pass the container transactionManager to Hibernate.
The classical answer is to set hibernate.transaction.manager_lookup_classto the matching class for your server.
假设您将 JPA 与 Spring 一起使用,并将 Hibernate 作为 JPA 实现。JPA事务模式是“JTA”,所以需要将容器transactionManager传递给Hibernate。经典的答案是hibernate.transaction.manager_lookup_class为您的服务器设置匹配的类。
However, I think it's a shame to have this depend of server specific configuration as you already found the transactionManager in Spring with <tx:jta-transaction-manager>.
但是,我认为这种依赖于特定于服务器的配置是一种耻辱,因为您已经在 Spring 中使用<tx:jta-transaction-manager>.
Is there a way to give this transactionManager to Hibernate with a configuration like
有没有办法使用类似的配置将此事务管理器提供给休眠状态
<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/>
The goal is to get rid of the org.hibernate.transaction.SunONETransactionManagerLookupproperty.
By the way, I really have two different server implementations in mind.
目标是摆脱org.hibernate.transaction.SunONETransactionManagerLookup财产。顺便说一下,我真的有两种不同的服务器实现。
EDIT : without the transaction manager configuration, Hibernate chokes when creating the EntityManagerFactory :
编辑:没有事务管理器配置,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.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
采纳答案by mP.
Unfortunately if one looks at the Hibernate APIs like many other JBoss products they have a a class typically called Configuration to hold most if not all the main config stuff. Unfortunately they (JBoss) seem to like to hold "Strings" for parameters and class to locate instances. Almost always its often impossible to simply set an actual premade ready to go setup.
不幸的是,如果像许多其他 JBoss 产品一样查看 Hibernate API,他们有一个通常称为 Configuration 的类来保存大部分(如果不是全部)主要配置内容。不幸的是,他们(JBoss)似乎喜欢为参数和类保存“字符串”来定位实例。几乎总是不可能简单地设置一个实际的预制准备好设置。
I am about to try something similar to the following for the very same reason you are mentioning.
出于与您提到的相同的原因,我将尝试类似于以下内容。
- Create an implementation of TransactionManagerLookup
- include a setter which takes a TM and sets a thread local variable + instance.
- pass the name of TML inside the properties you pass to the Configuration.
- When Your TML startsup copy the thread local variable to your instance fie.d.
- clear the threadlocal once everything is done.
- 创建 TransactionManagerLookup 的实现
- 包括一个 setter,它接受一个 TM 并设置一个线程局部变量 + 实例。
- 在您传递给配置的属性中传递 TML 的名称。
- 当您的 TML 启动时,将线程局部变量复制到您的实例字段。
- 一切都完成后清除threadlocal。
回答by Bozho
First of all - do you reallyneed JTA? Typically spring+hibernate don't require it. You can use a simple JpaTransactionManager/ HibernateTransactionManager.
首先 - 你真的需要 JTA 吗?通常 spring+hibernate 不需要它。您可以使用简单的JpaTransactionManager/ HibernateTransactionManager。
If you really want JTA, then you will need a JTA provider. If not running in an application server, check this questionfor how to use JTA in a servlet container. (Also take a look at this question)
如果您真的想要 JTA,那么您将需要一个 JTA 提供程序。如果不在应用程序服务器中运行,请查看此问题以了解如何在 servlet 容器中使用 JTA。(也看看这个问题)
Finally, hibernate docsspecify that, for container-managed transactions:
最后,hibernate 文档指定,对于容器管理的事务:
Declarative transaction demarcation is a standard feature of EJB, also known as container-managed transactions (CMT). In EJB 2.x you would use XML deployment descriptors to create your transaction assembly. In EJB 3.x you can use JDK 5.0 annotation metadata directly in your source code, a much less verbose approach. To enable CMT transaction demarcation for EJBs in Hibernate configuration:
- set
hibernate.transaction.manager_lookup_classto a lookup strategy for your JEE container- set
hibernate.transaction.factory_classtoorg.hibernate.transaction.CMTTransactionFactory
声明式事务划分是 EJB 的标准特性,也称为容器管理事务 (CMT)。在 EJB 2.x 中,您将使用 XML 部署描述符来创建事务程序集。在 EJB 3.x 中,您可以直接在源代码中使用 JDK 5.0 注释元数据,这是一种不那么冗长的方法。要在 Hibernate 配置中为 EJB 启用 CMT 事务划分:
- 设置
hibernate.transaction.manager_lookup_class为您的 JEE 容器的查找策略- 设置
hibernate.transaction.factory_class为org.hibernate.transaction.CMTTransactionFactory
The second point is perhaps something you've missed?
第二点也许是你错过的东西?
What the documentation says in addition to that (the next section) is that if you want declarative transaction, hibernate is not where you should look at. You'd need to create an interceptor. That's exactly what spring transaction managers are. And that would be my choice given your technology stack (Spring).
除此之外(下一部分)文档还说,如果您想要声明性事务,则 Hibernate 不是您应该查看的地方。您需要创建一个拦截器。这正是 spring 事务管理器的作用。鉴于您的技术堆栈(Spring),这将是我的选择。
If you wish not to rely on a single JTA provider, then make two builds. For example maven has "maven profiles", which allow to make builds for different environments.
如果您不想依赖单个 JTA 提供程序,则进行两次构建。例如 maven 有“maven 配置文件”,它允许为不同的环境进行构建。
回答by JGFMK
I've recently been doing some stuff with JPA/Grails and the configuration I used was along these lines:
我最近一直在用 JPA/Grails 做一些事情,我使用的配置是这样的:
Does this help at all?
这有帮助吗?
<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>

