Spring 4 + JPA (Hibernate 4) + JTA 事务管理器不会自动刷新

Spring 4 + JPA (Hibernate 4) + JTA transaction manager doesn't flush automatically

我正在从

迁移应用程序

Spring 3.0.5 + JPA 2.0 到 Spring 4 + JPA(休眠 4)

我已遵循迁移指南:https://github.com/spring-projects/spring-framework/wiki/Migrating-from-earlier-versions-of-the-spring-framework

该应用程序正在使用 JTA 事务管理器:Jencks / GeronimoPlatformTransactionManager(因为事务分布在数据源和 ESB 上)。

Spring/JPA 配置是:

<bean id="rduEntityManagerFactory" class="ch.vd.dsas.rdu.repository.crud.service.ExtendedLocalContainerEntityManagerFactoryBean"
    depends-on="rduTransactionManagerLocator,jGroupsCacheManagerPeerProviderFactoryLocator">
    <property name="persistenceUnitName" value="rduPersistenceUnit" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="${rdu.jpa.database}" />
        </bean>
    </property>
    <property name="persistenceUnitPostProcessors">
        <bean class="ch.vd.dsas.rdu.commons.tx.spring.JtaPersistenceUnitPostProcessor">
            <property name="jtaDataSource" ref="rduDataSource" />
        </bean>
    </property>
    <property name="jpaProperties" ref="jpaProperties"/>
</bean>

<util:properties id="jpaProperties">
    <prop key="javax.persistence.transactionType">JTA</prop>
    <prop key="javax.persistence.validation.mode">CALLBACK</prop>
    <prop key="hibernate.hbm2ddl.auto">${rdu.jpa.hbm2ddl.auto}</prop>
    <prop key="hibernate.current_session_context_class">jta</prop>
    <!-- Transaction properties -->
    <prop key="hibernate.transaction.jta.platform">ch.vd.dsas.rdu.ref.transaction.jencks.JencksTransactionManagerLookup</prop>
    <prop key="hibernate.transaction.manager_lookup_class">ch.vd.dsas.rdu.transaction.jencks.JencksTransactionManagerLookup</prop>
    <prop key="hibernate.default_schema">${rdu.datasource.schemaMetier}</prop>
    <!-- Debug properties -->
    <prop key="hibernate.format_sql">true</prop>
    <prop key="hibernate.show_sql">true</prop>
    <!-- Cache properties -->
    <prop key="hibernate.cache.use_second_level_cache">true</prop>
    <prop key="hibernate.cache.use_query_cache">true</prop>
    <prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.ReplicatedSingletonEhCacheRegionFactory</prop>
    <prop key="hibernate.cache.cluster_name">${rdu.hibernate.cache.jgroups.cluster.name}</prop>
    <prop key="net.sf.ehcache.configurationResourceName">/hibernate-ehcache.xml</prop>
</util:properties>

事务由注解驱动:

<tx:annotation-driven transaction-manager="rduJtaTransactionManager" />

事务管理器是这样声明的:

<!-- From Jencks org.jencks:jencks:2.2 -->
<bean id="rduJencksTransactionManager" class="org.jencks.factory.TransactionManagerFactoryBean" />

<bean id="rduJtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <qualifier value="rdu" />
    <property name="transactionManager" ref="rduJencksTransactionManager" />
    <property name="userTransaction" ref="rduJencksTransactionManager" />
</bean>

<bean id="rduTransactionManagerLocator" class="ch.vd.dsas.rdu.transaction.jencks.TransactionManagerLocator" factory-method="getInstance">
    <property name="transactionManager" ref="rduJencksTransactionManager"/>
</bean>

应用程序正在启动并访问数据并显示它。

但是没有执行插入/更新。

如果我更改数据并提交更改,应用程序会收到更改,但数据不会刷新到数据库。

我已经激活了日志并且我看到了交易:

rdu 2015-06-18 20:28:01,817 [ http-8080-1] DEBUG [ o.s.t.j.JtaTransactionManager] Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; 'rdu' rdu 2015-06-18 20:28:01,817 [ http-8080-1] DEBUG [ o.s.t.j.JtaTransactionManager] Participating in existing transaction rdu 2015-06-18 20:28:01,823 [ http-8080-1] DEBUG [ o.s.t.j.JtaTransactionManager] Initiating transaction commit

但没有任何内容发送到数据库。

如果我通过调试拦截执行并手动刷新 Hibernate 会话,数据就会更新。

JPA/Hibernate session 好像没有和事务协调。

我无法弄清楚配置中缺少什么以及为什么会话没有自动刷新。

希望你能帮我解决这个问题。

此致, 埃里克

问题是由于这个属性:

<prop key="hibernate.transaction.jta.platform">ch.vd.dsas.rdu.ref.transaction.jencks.JencksTransactionManagerLookup</prop>

hibernate.transaction.jta.platform 属性 与 hibernate.transaction.manager_lookup_class 不同,它应该指向 AbstractJtaPlatform 实现:

<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>