Spring HibernateTransactionManager 사물 관리 클래스 (HibernateTransactionObject)

저 희 는 Spring 에서 보통 HibernateTransactionManager 에 업 무 를 맡 깁 니 다. Aop 설정 업 무 를 통 해 업 무 를 이런 종류 에 맡 긴 후에 이런 종류 로 업 무 를 관리 하고 제공 합 니 다.여기 서 그것 이 어떻게 실현 되 었 는 지, 다음은 우리 가 소스 코드 에 깊이 들 어가 자.
public class HibernateTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {

우선 이 종 류 는 AbstractPlatformTransactionManager 류 를 계승 하고 일련의 인 터 페 이 스 를 실현 했다.
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

AbstractPlatformTransactionManager 라 는 추상 적 인 종 류 는 인터페이스의 getTransaction (TransactionDefinition definition definition) 방법 을 실 현 했 습 니 다. 이 방법 에서 doGetTransaction (), doBegin () 방법 과 다른 방법 을 실 행 했 습 니 다. 여기 서 일일이 소개 하지 않 겠 습 니 다.
하위 클래스 인 HibernateTransactionManager 클래스 로 돌아 가면 부모 클래스 의 doGetTransaction () 방법 과 doBegin (), doCommit () 을 다시 썼 습 니 다. 그래서 이 방법 이 우리 가 주로 토론 해 야 할 것 입 니 다. 그리고 doCommit ()...
부모 클래스 의 getTransaction (TransactionDefinition definition definition) 을 보면 먼저 doGetTransaction () 을 한 다음 doBegin () 을 걷는다.
doGetTransaction () 방법 소스 코드 를 살 펴 보 겠 습 니 다.
	protected Object doGetTransaction() {
		HibernateTransactionObject txObject = new HibernateTransactionObject();//  new  HibernateTransactionObject  
		txObject.setSavepointAllowed(isNestedTransactionAllowed());//       
               //        sessionFacoty key      sessionHolder,
		SessionHolder sessionHolder =
				(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
		if (sessionHolder != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Found thread-bound Session [" +
						SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction");
			}
			txObject.setSessionHolder(sessionHolder);// sessionHolder   txObject  
		}
		else if (this.hibernateManagedSession) {//               ,         thread, Spring   
			try {
				Session session = getSessionFactory().getCurrentSession();//            
				if (logger.isDebugEnabled()) {
					logger.debug("Found Hibernate-managed Session [" +
							SessionFactoryUtils.toString(session) + "] for Spring-managed transaction");
				}
				txObject.setExistingSession(session);//       sessionHolder txObject  , set     session    
			}
			catch (HibernateException ex) {
				throw new DataAccessResourceFailureException(
						"Could not obtain Hibernate-managed Session for Spring-managed transaction", ex);
			}
		}
               //        DataSource,    afterPropertiesSet()  sessionFactory   DataSource
		if (getDataSource() != null) {
			ConnectionHolder conHolder = (ConnectionHolder)
					TransactionSynchronizationManager.getResource(getDataSource());//                ,   doBegin()     
			txObject.setConnectionHolder(conHolder);//        sessionHolder   txObject 
		}
		return txObject;
	}

위 에 있 는 doGetTransaction () 방법 이 끝나 면 HibernateTransactionObject txObject 대상 을 만 들 었 습 니 다. 이 대상 도 주인공 이 고 이 대상 에 두 개의 속성 을 채 워 서 이 두 속성 에 값 을 부여 합 니 다. 하 나 는 session holder 이 고 다른 하 나 는 connection Holder 입 니 다. 즉, session 과 connect 입 니 다.
업무 논리 에 있 는 C 방법 에 A, B 방법 이 포함 되 어 있 을 때 동시에 호출 됩 니 다. 하나의 사무 만 열 었 습 니 다. session 은 현재 스 레 드 에 있 는 것 과 같 습 니 다. session Factory Utils. dogetSession () 을 직접 뛰 었 습 니 다.
action 호출 을 분리 할 때 먼저 A 후 B 는 A 에 게 사 무 를 열 고 B 에 게 사 무 를 열 지만 스 레 드 에서 session 을 가 져 옵 니 다.
다음은 doBegin () 방법 입 니 다. 새로운 대상 TransactionDefinition 사물 설명 을 도입 하고 일부 코드 는 생략 합 니 다.
protected void doBegin(Object transaction, TransactionDefinition definition) {
		HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;//  txObject  ,     HibernateTransactionObject
               //   sessionHolder    ,        hibernate   session,    session  SessionHolder 
		Session session = null;

		try {//  txObject  sessionHolder     
			if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
				Interceptor entityInterceptor = getEntityInterceptor();//       
				Session newSession = (entityInterceptor != null ?
						getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());
				if (logger.isDebugEnabled()) {
					logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) +
							"] for Hibernate transaction");
				}
				txObject.setSession(newSession);
			}
                       //   sessionHolder   session, hibernateTransaction   
			session = txObject.getSessionHolder().getSession();
			if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
				// We're allowed to change the transaction settings of the JDBC Connection.
				if (logger.isDebugEnabled()) {
					logger.debug(
							"Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
				}
				Connection con = session.connection();
				Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
				txObject.setPreviousIsolationLevel(previousIsolationLevel);
			}
			else {
				  //     Aop      isolation  
				// Not allowed to change the transaction settings of the JDBC Connection.
				if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
					// We should set a specific isolation level but are not allowed to...
					throw new InvalidIsolationLevelException(
							"HibernateTransactionManager is not allowed to support custom isolation levels: " +
							"make sure that its 'prepareConnection' flag is on (the default) and that the " +
							"Hibernate connection release mode is set to 'on_close' (SpringTransactionFactory's default). " +
							"Make sure that your LocalSessionFactoryBean actually uses SpringTransactionFactory: Your " +
							"Hibernate properties should *not* include a 'hibernate.transaction.factory_class' property!");
				}
				if (logger.isDebugEnabled()) {
					logger.debug(
							"Not preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
				}
			}
				 //     Aop      read-only  ,
				 if (definition.isReadOnly() && txObject.isNewSession()) {
					 		// Just set to NEVER in case of a new Session for this transaction.
					 		session.setFlushMode(FlushMode.MANUAL);
				 	}
				 if (!definition.isReadOnly() && !txObject.isNewSession()) {
				//        ,       session,             session,     true(OpenSessionView)
				// We need AUTO or COMMIT for a non-read-only transaction.
						FlushMode flushMode = session.getFlushMode();
						if (flushMode.lessThan(FlushMode.COMMIT)) {
								session.setFlushMode(FlushMode.AUTO);
								txObject.getSessionHolder().setPreviousFlushMode(flushMode);
						}
				}
					Transaction hibTx;
					// Register transaction timeout.
					int timeout = determineTimeout(definition);
				if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
					hibTx = session.getTransaction();
					//          ,    hibTx.begin();
					hibTx.setTimeout(timeout);
				}else {
					// hibernate      txObject sessionHolder   ,  sessionHolder      .
					hibTx = session.beginTransaction();
				} 
				// Transaction hibTx   txObject , txObject    ,               	
				txObject.getSessionHolder().setTransaction(hibTx);
				// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
				if (getDataSource() != null) {
				         Connection con = session.connection();
				         ConnectionHolder conHolder = new ConnectionHolder(con);//  connection
				     if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				              conHolder.setTimeoutInSeconds(timeout);
				      }
				     if (logger.isDebugEnabled()) {
				    	 	logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");
				     	}
				     //       connection         .
				     TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
				     //    txObject ConnectionHolder  ,    con  null
				     txObject.setConnectionHolder(conHolder);
				 }
				//     sessionHolder,         // Bind the session holder to the thread.
				if (txObject.isNewSessionHolder()) {
						//              sessionHolder,       false,open  true
						TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
						//         
				}
					// sessionHolder       ,        。
				txObject.getSessionHolder().setSynchronizedWithTransaction(true);
				}
}

4. 567913. doCommit () 는 모두 가 사무 제출 이라는 것 을 알 고 있 습 니 다. 물론 제출 하기 전에 도 많은 일 을 했 습 니 다. 예 를 들 어 session 을 비 우 는 방법 은 일일이 열거 되 지 않 았 습 니 다. 부모 류 AbstractPlatformTransactionManager 의 processCommit () 방법 을 볼 수 있 습 니 다. prepareForCommit 를 먼저 뛰 어 제출 을 준비 하 는 방법 등 을 볼 수 있 습 니 다.
스 레 드 에 연 결 된 사무, rollback.
더 자세히 보기:
http://sailinglee.iteye.com/blog/598908
http://books.google.com.hk/books?id=jRVp2INtY1AC&pg=PA222&lpg=PA222&dq=HibernateTransactionManager#v=onepage&q=HibernateTransactionManager&f=false
TransactionDefinition:
http://book.51cto.com/art/200909/149403.htm

좋은 웹페이지 즐겨찾기