在EJB 中 配置Hibernate支持JTA
程序员文章站
2022-05-23 15:53:54
...
Finally, 搞清楚了些Hibernate 的对JTA 的支持。
有几个非常重要的property 需要配置
<prop key="hibernate.current_session_context_class">
jta
</prop>
<prop key="hibernate.transaction.manager_lookup_class">
org.hibernate.transaction.WebSphereTransactionManagerLookup
</prop>
<prop key="hibernate.transaction.factory_class">
org.hibernate.transaction.CMTTransactionFactory
</prop>
1, hibernate.transaction.manager_lookup_class 是用来在SessionFactory 起来的时候调用在 获取 TransactionManager 的, 在 WebSphere 下比较特殊用 这个 WebSphereTransactionManagerLookup。 其它的很多应用服务器比如GlassFish 是通过JNDI 来得到 TransactionManager 的。 GlassFish 下用
org.hibernate.transaction.SunONETransactionManagerLookup
这样Hibernate就可以拿到正确的TransactionManager 了。
2, hibernate.current_session_context_class 是用来配置 SessionContext 的, 它跟SessionFactory 一样可以理解成是个单例。 一个Hibernate configuration 对应一个SessionFactory, 一个SessionFactory 对应一个CurrentSessionContext. 在应用程序中 我们最好是都通过 SessionFactory.getCurrentSession() 来获取Session。它的过程大概是这样的,
2.1 SessionFactory.getCurrentSession() 会调用 JTASessionContext.currentSession();
2.2 JTASessionContext 维护了一个 trasaction 跟 session 的 map。JTASessionContext.currentSession() 的逻辑是先 根据TractionManager 获取当前 tranction , 然后 来这个map 找对应的session 如果没有 就创建一个新的SessionImpl。
2.3 在SessionImpl 建构函数中 会创建一个新的JDBCContext. 这个JDBCContext 名字比较悲催啊其实不管是JDBC 还是JTA 都是需要它的。 以前被它给忽悠了, 其实在JTA的环境下它的作用更大的说。在它的建构函数中 调用了一个 非常重要的方法 registerSynchronizationIfPossible。
public boolean registerSynchronizationIfPossible() {
if ( isTransactionCallbackRegistered ) {
// we already have a callback registered; either a local
// (org.hibernate.Transaction) transaction has accepted
// callback responsibilities, or we have previously
// registered a transaction synch.
return true;
}
boolean localCallbacksOnly = owner.getFactory().getSettings()
.getTransactionFactory()
.areCallbacksLocalToHibernateTransactions();
if ( localCallbacksOnly ) {
// the configured transaction-factory says it only supports
// local callback mode, so no sense attempting to register a
// JTA Synchronization
return false;
}
TransactionManager tm = owner.getFactory().getTransactionManager();
if ( tm == null ) {
// if there is no TM configured, we will not be able to access
// the javax.transaction.Transaction object in order to
// register a synch anyway.
return false;
}
else {
try {
if ( !isTransactionInProgress() ) {
log.trace( "TransactionFactory reported no active transaction; Synchronization not registered" );
return false;
}
else {
javax.transaction.Transaction tx = tm.getTransaction();
if ( JTAHelper.isMarkedForRollback( tx ) ) {
// transactions marked for rollback-only cause some TM impls to throw exceptions
log.debug( "Transaction is marked for rollback; skipping Synchronization registration" );
return false;
}
else {
if ( hibernateTransaction == null ) {
hibernateTransaction = owner.getFactory().getSettings().getTransactionFactory().createTransaction( this, owner );
}
tx.registerSynchronization( new CacheSynchronization(owner, this, tx, hibernateTransaction) );
isTransactionCallbackRegistered = true;
log.debug("successfully registered Synchronization");
return true;
}
}
}
catch( HibernateException e ) {
throw e;
}
catch (Exception e) {
throw new TransactionException( "could not register synchronization with JTA TransactionManager", e );
}
}
}
这个方法 中的 owner.getFactory().getSettings().getTransactionFactory() 就用到了三个配置参数中的最后一个 org.hibernate.transaction.CMTTransactionFactory 。 这个TransactionFactory 的 areCallbacksLocalToHibernateTransactions 返回 false。 如果我们不配置这个参数 owner.getFactory().getSettings().getTransactionFactory() 拿到的就是 JDBCTransactionFactory 了, 它就当然不会走到后面的
tx.registerSynchronization( new CacheSynchronization(owner, this, tx, hibernateTransaction) );
这一行代码 会在JTA transaction 注册一个 Synchronization:CacheSynchronization。
2.4 在CacheSynchronization 实现的 beforeCompletion 方法中 调用 sessionImpl.managedFlush() 方法。
这样我们可以看到 JTA 下面 transaction 跟 session 是 一对一, 在transaction 结束的时候 flush , close session。 当然我们需要我们通过 JTASessionContext.currentSession() 来保证 都是走 JTASessionContext 来管理 session。
上一篇: Java 动态初始化类
下一篇: PHP代码优化24条真经
推荐阅读
-
在nginx中配置pathinfo模式支持thinkphp的URL重写
-
Mysql在Spring中配置hibernate的字符编码格式
-
在 Tomcat 中配置 SSL/TLS 以支持 HTTPS
-
在nginx中配置pathinfo模式支持thinkphp的URL重写
-
Hibernate的配置在myeclipse中的一个坑,希望帮助同样碰到问题的人
-
修改@Scheduled注解增加enable参数使其支持在配置文件中打开和关闭
-
配置apache以支持php 在apache主配置文件httpd.conf中Include自
-
在resin3.0中配置hibernate2.1.2连mysql
-
详解在Hibernate中配置数据库方言的作用和好处
-
在EJB 中 配置Hibernate支持JTA