首页 文章

在JPA / Hibernate中使用Spring定义的transactionManager

提问于
浏览
10

假设您将JPA与Spring一起使用,将Hibernate用作JPA实现 . JPA事务模式是"JTA",因此您需要将容器transactionManager传递给Hibernate . 经典的答案是将 hibernate.transaction.manager_lookup_class 设置为服务器的匹配类 .

但是,我认为让这取决于服务器特定配置是一种耻辱,因为您已经在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

    不幸的是,如果像许多其他JBoss产品那样查看Hibernate API,他们就会有一个通常称为Configuration的类来保存大部分(如果不是全部)主配置 . 不幸的是,他们(JBoss)似乎喜欢为参数和类保存“Strings”来定位实例 . 几乎总是不可能简单地设置一个实际的预制准备好去设置 .

    我将要提出类似于以下内容的内容,原因与您提到的相同 .

    • 创建TransactionManagerLookup的实现

    • 包含一个setter,它接受一个TM并设置一个线程局部变量实例 .

    • 在传递给Configuration的属性中传递TML的名称 .

    • 当您的TML启动时,将线程局部变量复制到您的实例fie.d.
      一切都完成后

    • 清除threadlocal .

  • 0

    首先 - 你真的需要JTA吗?通常 Spring 天冬眠不需要它 . 你可以使用一个简单的 JpaTransactionManager / HibernateTransactionManager .

    如果你真的想要JTA,那么你需要一个JTA提供者 . 如果未在应用程序服务器中运行,请检查this question以了解如何在servlet容器中使用JTA . (另请看this question

    最后,hibernate docs为容器管理的事务指定:

    声明式事务划分是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

    第二点可能是你错过了什么?

    除了那个文档(下一节)之外,文档说的是如果你想要声明式事务,那么hibernate不是你应该看的地方 . 你需要创建一个拦截器 . 这正是 Spring 季交易经理所追求的 . 鉴于您的技术堆栈(Spring),这将是我的选择 .

    如果您不希望依赖单个JTA提供程序,那么请进行两次构建 . 例如,maven有“maven profiles”,它允许为不同的环境进行构建 .

  • 1

    我最近用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>
    

相关问题