在EJB 中 配置Hibernate支持JTA

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

扫描二维码关注公众号,回复: 733408 查看本文章

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


猜你喜欢

转载自bruce008.iteye.com/blog/1434345
EJB