【问题标题】:Spring4 + Hibernate4 + JTA Write Operations FailSpring4 + Hibernate4 + JTA 写操作失败
【发布时间】:2014-12-25 14:23:48
【问题描述】:

我正在将 JBoss 5 应用程序上的旧 Spring 3、Hibernate 3、JTA 迁移到最新版本(Spring 4.1.0.RELEASE、Hibernate 4.3.6.Final、JBoss Wildfly 8.1)。似乎 Spring 4.1.0.RELEASE 和 Hibernate 4.3.6.Final 确实 NOT 一起工作以支持使用 LocalSessionFactoryBeanHibernateTransactionManager 如下配置。只读获取操作似乎工作正常。

要迁移,org.springframework.orm.hibernate3.support.HibernateDaoSupport 已更新为 org.springframework.orm.hibernate4.support.HibernateDaoSupport。有问题的代码正在尝试使用 getHibernateTemplate().saveOrUpdate(myObject); 进行保存,其中 myObject 是要保存的对象(适用于 Spring3 + Hibernate 3)。代码可以编译,但在运行时我看到代码在以下位置引发了调用异常:

https://github.com/spring-projects/spring-framework/blob/master/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/HibernateTemplate.java#L325

问题:

  1. getSessionFactory().getCurrentSession() 调用触发的 Hibernate 会话的打开/关闭是否存在问题(性能或其他)?如果是这样,配置中有没有可以设置的东西来避免它?

  2. HibernateTemplate 在处理异常时总是将新打开的会话设置为 FlushMode.MANUAL。而且,在调试器中,我看到这无法通过以下位置检查写入操作:

https://github.com/spring-projects/spring-framework/blob/master/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/HibernateTemplate.java#L1134

请注意,设置 getHibernateTemplate().setCheckWriteOperations(false); 会绕过 Spring 检查,但 getHibernateTemplate().saveOrUpdate(myObject) 调用会在 Hibernate 代码中静默失败不会抛出任何异常,也不会将任何内容写入数据库。我需要进行哪些配置更改才能提交写操作?

Bean 定义:

这里是来自 application-context.xml Spring 配置文件的相关 bean 定义 sn-ps:

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<tx:annotation-driven/>

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="false">
    <property name="jndiName" value="java:jboss/datasources/jdbc/my-srvr"/>
    <property name="cache">
        <value>false</value>
    </property>
    <property name="proxyInterface">
        <value>javax.sql.DataSource</value>
    </property>
</bean>

<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" lazy-init="true">

    <property name="dataSource" ref="dataSource"/>

    <property name="mappingResources">
        <list>
            <value>com/mydomain/dao/Hib.hib.xml</value>
        </list>
    </property>

    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.generate_statistics">false</prop>

            <!-- JTA  -->
            <prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory</prop>
            <prop key="hibernate.flushMode">AUTO</prop>
            <prop key="jta.UserTransaction">java:jboss/UserTransaction</prop>
            <prop key="jta.TransactionManager">java:jboss/TransactionManager</prop>
            <prop key="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform</prop>
            <prop key="hibernate.current_session_context_class">org.hibernate.context.internal.JTASessionContext</prop>
            <!--prop key="hibernate.transaction.manager_lookup_class">
                org.hibernate.transaction.JBossTransactionManagerLookup
            </prop-->

            <!-- Turn caching off to focus on JTA issues-->
            <prop key="hibernate.cache.use_second_level_cache">false</prop>
            <prop key="hibernate.cache.use_query_cache">false</prop>
            <!--prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop-->
            <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

            <prop key="net.sf.ehcache.configurationResourceName">sample-ehcache.xml</prop>
        </props>
    </property>
    <!--No equivalent class in Spring4; comment out for now-->
    <!--property name="eventListeners">
        <map>
            <entry key="merge">
                <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
            </entry>
        </map>
    </property-->
</bean>

注意:遗留 bean 定义的一个重要变化是从 org.springframework.transaction.jta.JtaTransactionManager 更改为 org.springframework.orm.hibernate4.HibernateTransactionManager .

JNDI 视图

部署后,JBoss Wildfly 中的 JNDI 视图如下(当然,每次部署时对象引用都会改变):

java:jboss

TransactionManager TransactionManagerDelegate@49e6e9c8

TransactionSynchronizationRegistry TransactionSynchronizationRegistryImple@40cd0746

用户事务用户事务

jaas java:jboss/jaas/ 上下文代理

【问题讨论】:

  • 如果你打电话给getHibernateTemplate().saveOrUpdate(myObject);而不是getHibernateTemplate().merge(myObject);会发生什么?
  • 似乎没有什么不同。我将其追踪到 Hibernate 的 TransactionCoordinatorImpl,它尝试注册 jta 同步并返回:github.com/hibernate/hibernate-orm/blob/master/hibernate-core/…
  • 我建议在 Spring 或 Hibernate 论坛上发帖,那里的用户可能具有诊断此问题所需的专业知识。在此处包含帖子链接以及在这些论坛上返回此问题的链接,以便所有内容保持最新。
  • 如果您认为该信息与您的问题相关,我还建议您编辑您的问题以包含您正在使用的确切版本号。
  • 我已经为问题添加了特定版本,感谢您的建议。我先在 Spring 论坛上发帖,但它现在似乎已退休。所以我按照这篇博文的建议在 StackOverflow 上发帖:spring.io/blog/2014/06/18/retiring-the-forum-spring-io-website

标签: jta wildfly spring-transactions hibernate-4.x spring-4


【解决方案1】:

所以我终于让写操作在遗留代码中工作。以下是我为使代码正常工作所遵循的步骤:

  1. 确保您使用的是 Hibernate 特定的事务管理器org.springframework.orm.hibernate4.HibernateTransactionManager 通用的org.springframework。 transaction.jta.JtaTransactionManager

  2. 验证注释是否已启用。

  3. @Transactional 注释 (org.springframework.transaction.annotation.Transactional) 添加到执行保存/更新/删除等操作的方法中。旧代码无需此注释即可工作,但现在,对于最新版本,需要启用写入操作。

  4. 在我的例子中,我一添加注释就遇到了一堆自动连接问题。根本原因是某些实现类,而不是接口,被用于在@Service 级别的类中自动连接属性。更改引用以使用接口修复了该问题。您可以在 this one 等其他主题上阅读更多相关信息。

我不得不搜索并重复这些步骤来修复遗留代码中的所有此类实例。请注意,通过OpenSessionInViewFilterFlushMode 全局设置为 AUTO 并不是一个干净的解决方案; Spring 默认将 FlushMode 设置为 MANUAL 是有充分理由的。当存在 @Transactional 注释时,Spring 会进行必要的运行时调整以支持写入操作。我一直调试到 Hibernate org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl 类,并且 Jta 同步在上面的设置中运行良好。希望这可以帮助任何坚持尝试将遗留代码迁移到最新版本的人。

【讨论】:

    猜你喜欢
    • 2014-04-30
    • 1970-01-01
    • 2017-03-11
    • 2023-03-29
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    • 2016-02-10
    相关资源
    最近更新 更多