`
shz2008bj
  • 浏览: 481627 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

HibernateTemplate中HibernateCallback的事务

阅读更多
 

HibernateTemplate中HibernateCallback的事务

目的:使用HibernateTemplate执行execute(new HibernateCallback())方法,从HibernateCallback中得到session,在此session中做多个操作,并希望这些操作位于同一个事务中。
      如果你这样写(1):
      
public static void main(String ss[]) {
        CtxUtil.getBaseManager().getHibernateTemplate().execute(
new HibernateCallback() {
            
public Object doInHibernate(Session session) throws HibernateException, SQLException {
                
// 保存stu1
                Student stu1 = new Student();
                stu1.setName(
"aaaa");// 在数据库中,name字段不允许为null
                session.save(stu1);
                session.flush();//实际上,如果不是程序员"手痒"来调用这个flush(),HibernateTemplate中session的事务处理还是很方便的

                Student stu2 
= new Student();
                session.save(stu2);
// 没有设置name字段,预期会报出例外
                session.flush();
                
return null;
            }

        }
);

    }
      你期望spring在执行完execute回调后,在关闭session的时候提交事务,想法是很好的,但spring并不会这么做.让我们来看看在 Hibernate的源代码中,session.beginTransation()做了什么事。看如下代码(2):
public Transaction beginTransaction() throws HibernateException {
        errorIfClosed();
        
if ( rootSession != null ) {
            
// todo : should seriously consider not allowing a txn to begin from a child session
            
//      can always route the request to the root session
            log.warn( "Transaction started on non-root session" );
        }

        Transaction result 
= getTransaction();
        result.begin();
        
return result;
    }
这个方法中的result是一个org.hibernate.transaction.JDBCTransaction实例,而方法中的getTransaction()方法源代码为(3):
public Transaction getTransaction() throws HibernateException {
        
if (hibernateTransaction==null{
            log.error(owner.getFactory().getSettings()
                    .getTransactionFactory().getClass());
            hibernateTransaction 
= owner.getFactory().getSettings()
                    .getTransactionFactory()
                    .createTransaction( 
this, owner );
        }

        
return hibernateTransaction;
    }
再次追踪,owner.getFactory().getSettings() .getTransactionFactory()的createTransaction()方法源代码如下(4):
public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)
    
throws HibernateException {
        
return new JDBCTransaction( jdbcContext, transactionContext );
    }
它返回了一个JDBCTransaction,没什么特别的。
在代码2中,执行了result.begin(),其实也就是JDBCTransaction实例的begin()方法,来看看(5):

public void begin() throws HibernateException {
        
if (begun) {
            
return;
        }

        
if (commitFailed) {
            
throw new TransactionException("cannot re-start transaction after failed commit");
        }

        log.debug(
"begin");
        
try {
            toggleAutoCommit 
= jdbcContext.connection().getAutoCommit();
            
if (log.isDebugEnabled()) {
                log.debug(
"current autocommit status: " + toggleAutoCommit);
            }

            
if (toggleAutoCommit) {
                log.debug(
"disabling autocommit");
                jdbcContext.connection().setAutoCommit(
false);//把自动提交设为了false
            }

        }
 catch (SQLException e) {
            log.error(
"JDBC begin failed", e);
            
throw new TransactionException("JDBC begin failed: ", e);
        }

        callback 
= jdbcContext.registerCallbackIfNecessary();
        begun 
= true;
        committed 
= false;
        rolledBack 
= false;

        
if (timeout > 0{
            jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);
        }


        jdbcContext.afterTransactionBegin(
this);
    }

在直接使用Hibernate时,要在事务结束的时候,写上一句:tx.commit(),这个commit()的源码为:
public void commit() throws HibernateException {
        
if (!begun) {
            
throw new TransactionException("Transaction not successfully started");
        }


        log.debug(
"commit");

        
if (!transactionContext.isFlushModeNever() && callback) {
            transactionContext.managedFlush(); 
// if an exception occurs during
            
// flush, user must call
            
// rollback()
        }


        notifyLocalSynchsBeforeTransactionCompletion();
        
if (callback) {
            jdbcContext.beforeTransactionCompletion(
this);
        }


        
try {
            commitAndResetAutoCommit();//重点代码,它的作用是提交事务,并把connection的autocommit属性恢复为true
            log.debug(
"committed JDBC Connection");
            committed 
= true;
            
if (callback) {
                jdbcContext.afterTransactionCompletion(
truethis);
            }

            notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_COMMITTED);
        }
 catch (SQLException e) {
            log.error(
"JDBC commit failed", e);
            commitFailed 
= true;
            
if (callback) {
                jdbcContext.afterTransactionCompletion(
falsethis);
            }

            notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_UNKNOWN);
            
throw new TransactionException("JDBC commit failed", e);
        }
 finally {
            closeIfRequired();
        }

    }

上面代码中,commitAndResetAutoCommit()方法的源码如下:
private void commitAndResetAutoCommit() throws SQLException {
        
try {
            jdbcContext.connection().commit();//这段不用说也能理解了
        }
 finally {
            toggleAutoCommit();//这段的作用是恢复connection的autocommit属性为true
        }

    }

上述代码的toggleAutoCommit()源代码如下:
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics