欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

在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。