Spring4 + Hibernate4 + JTA写入操作失败 [英] Spring4 + Hibernate4 + JTA Write Operations Fail

查看:152
本文介绍了Spring4 + Hibernate4 + JTA写入操作失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将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在 LocalSessionFactoryBean HibernateTransactionManager ,如下所示.只读的get操作似乎可以正常工作.

I am migrating a legacy Spring 3, Hibernate 3, JTA on JBoss 5 application to the latest versions (Spring 4.1.0.RELEASE, Hibernate 4.3.6.Final, JBoss Wildfly 8.1). It seems that Spring 4.1.0.RELEASE and Hibernate 4.3.6.Final do NOT work together in supporting transactions for write operations with the LocalSessionFactoryBean and the HibernateTransactionManager as configured below. Read-only get operations appear to be working ok.

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

To migrate, org.springframework.orm.hibernate3.support.HibernateDaoSupport has been updated to org.springframework.orm.hibernate4.support.HibernateDaoSupport. The code in question is trying to save with getHibernateTemplate().saveOrUpdate(myObject); where myObject is the object to save (that works in Spring3 + Hibernate 3). The code compiles but at runtime I see the code throw an exception for the call at:

问题:

  1. getSessionFactory().getCurrentSession()触发的Hibernate会话的打开/关闭是否引起问题(性能还是其他问题)?如果是这样,那么配置中是否可以设置某些内容来避免这种情况?

  1. Is the opening/closing of Hibernate sessions triggered by the getSessionFactory().getCurrentSession() call an issue (performance or otherwise)? If so, is there something in the configuration that can be set to avoid it?

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

HibernateTemplate always sets the newly opened session to FlushMode.MANUAL while handling the exception. And, in the debugger, I see that this fails the check for write operations at:

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

Note that setting getHibernateTemplate().setCheckWriteOperations(false); bypasses the Spring check but the getHibernateTemplate().saveOrUpdate(myObject) call silently fails in the Hibernate code without throwing any exceptions and nothing gets written to the database. What config change(s) do I need to make to get the write operations to commit?

Bean定义:

以下是application-context.xml Spring配置文件中的相关bean定义片段:

Here're the relevant bean definition snippets from the application-context.xml Spring config file:

<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 的变化.

Note: An important change from the legacy bean definition is the change from org.springframework.transaction.jta.JtaTransactionManager to org.springframework.orm.hibernate4.HibernateTransactionManager.

JNDI视图

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

Once deployed, the JNDI View in JBoss Wildfly is as below (of course the object references change every deployment):

java:jboss

java:jboss

TransactionManager TransactionManagerDelegate @ 49e6e9c8

TransactionManager TransactionManagerDelegate@49e6e9c8

TransactionSynchronizationRegistry TransactionSynchronizationRegistryImple @ 40cd0746

TransactionSynchronizationRegistry TransactionSynchronizationRegistryImple@40cd0746

UserTransaction UserTransaction

UserTransaction UserTransaction

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

jaas java:jboss/jaas/ Context proxy

推荐答案

所以我终于让写操作在旧代码中起作用.这是我使代码正常运行的步骤:

So I finally got the write operations to work in the legacy code. Here are the steps I followed to get the code working:

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

验证注释已启用.

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

Add the @Transactional annotation (org.springframework.transaction.annotation.Transactional) to the methods where you perform the save/update/delete etc operations. The legacy code worked without needing this annotation but now, for the latest versions, it is required to enable write operations.

就我而言,添加注释后,我遇到了很多自动装配问题.根本原因是,某些实现类(而不是接口)被用于自动连接@Service级别类的属性.更改引用以使用接口可解决该问题.您可以在其他线程(例如

In my case, I got a bunch of auto-wiring issues as soon as I added the annotation. The root cause turned out to be that some implementation classes, not interfaces, were being used to auto-wire properties at the @Service level classes. Changing the references to use the interfaces fixed that issue. You can read more about it on other threads such as this one.

我必须搜索并重复步骤以在旧版代码中修复所有此类实例.请注意,通过

I had to search and repeat the steps to fix all such instances in the legacy code. Note that setting the FlushMode to AUTO globally via OpenSessionInViewFilter is not a clean solution; there is a good reason why Spring sets the FlushMode to MANUAL by default. Spring makes the necessary runtime tweaks to support write operations when the @Transactional annotation is present. I debugged all the way to the Hibernate org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl class and the Jta synchronization works fine with the setup above. Hope this helps anyone stuck in trying to migrate legacy code to the latest versions.

这篇关于Spring4 + Hibernate4 + JTA写入操作失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆