在一些具有非常严格的XADataSource实现的JTA环境中(目前来说只是WebLogic和WebSphere的某些版本)当你将Hibernate配置成不感知JTA PlatformTransactionManager 对象时,容器可能会在应用服务器日志中报出一些警告和异常。 这些警告和异常通常会说:“正在被访问的连接不再有效,或者JDBC连接不再有效,可能由于事务不再处于激活状态”。下面是一个从WebLogic上抛出的异常:
java.sql.SQLException: The transaction is no longer active - status: 'Committed'.
No further JDBC access is allowed within this transaction.
这样的错误警告很容易解决:只要简单的把Hibernate配置成感知到JTA PlatformTransactionManager 实例的存在即可,同时将他们进行同步(与Spring同步)。可以有两种方法达到这种效果:
如果你已经在你的application context中定义并获取了JTA PlatformTransactionManager 对象(或许来自通过 JndiObjectFactoryBean 得到的JNDI)并已经将它注入到类似Spring的 JtaTransactionManager 中, 那么最简单的方式就是指定这个bean的引用作为 LocalSessionFactoryBean 的 jtaTransactionManager 属性。Spring将使这个对象被Hibernate所感知。
多数情况下,你还没有得到JTA的 PlatformTransactionManager 实例(由于Spring的 JtaTransactionManager 能够自己找到它),所以你需要自行配置Hibernate并直接寻找资源。 正如Hibernate文档中提到的,这可以通过在Hibernate配置一个应用服务器特定的 TransactionManagerLookup 类来完成。
对于恰当的使用方法,你无需了解更多的东西。但是我们在这里将描述一下,对于将Hibernate配置为感知或者不感知JTA的 PlatformTransactionManager 对象这两种情况下,整个事务的执行顺序。
Hibernate被配置成不感知JTA PlatformTransactionManager 的情况下,当一个JTA事务提交时,整个事件的执行顺序如下:
JTA 事务提交
Spring的 JtaTransactionManager 同步到JTA事务,它被JTA事务管理器通过调用 afterCompletion 执行回调。
在所有其他活动中,这将由Spring向Hibernate触发一个回调,通过Hibernate的 afterTransactionCompletion 回调(用于清除Hibernate缓存),然后紧跟着一个明确的Hibernate Session的 close() 调用。 这将使Hibernate试图去关闭JDBC的Connection。
在某些环境中,Connection.close() 的调用将会触发一个警告或者错误信息。 这是由于特定的应用服务器将不再考虑Connection的可用性,因为此时事务已经被提交了。
Hibernate被配置成感知JTA的 PlatformTransactionManager 的情况下,当一个JTA事务提交时,整个事件的执行顺序如下:
JTA 事务准备提交
Spring的 JtaTransactionManager 同步到JTA事务,因而它被JTA事务管理器通过调用 beforeCompletion 执行回调。
Spring能感知到Hibernate自身被同步到JTA Transaction,因而表现得与先前那种情况有所不同。 假设Hibernate的 Session 需要被关闭,Spring将负责关闭它。
JTA 事务提交
Hibernate将与JTA transaction进行同步,因而它被JTA事务管理器通过调用 afterCompletion 执行回调,并且适时地清除缓存。
标签: hibernate