HibernateTemplate中HibernateCallback的事务
    
  目的:使用HibernateTemplate执行execute(new HibernateCallback())方法,从HibernateCallback中得到session,在此session中做多个操作,并希望这些操作位于同一个事务中。 
 
    
如果你这样写(1):
           
 
    
       public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
          
           CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
          
                  CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
            
             public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
            
                        
          
          
            public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
              
               //
            
            
               保存stu1
                              
            
            
              //
            
            
               保存stu1
            
            
              
               Student stu1 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
            
            
                              Student stu1 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
              
               stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
               在数据库中,name字段不允许为null
                              stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
               在数据库中,name字段不允许为null
            
            
              
               session.save(stu1);
            
            
                              session.save(stu1);
              
               session.flush();//实际上,如果不是程序员"手痒"来调用这个flush(),HibernateTemplate中session的事务处理还是很方便的
                              session.flush();//实际上,如果不是程序员"手痒"来调用这个flush(),HibernateTemplate中session的事务处理还是很方便的
              
               
              
               Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
                              Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
              
               session.save(stu2);
            
            
              //
            
            
               没有设置name字段,预期会报出例外
                              session.save(stu2);
            
            
              //
            
            
               没有设置name字段,预期会报出例外
            
            
              
               session.flush();
            
            
                              session.flush();
              
               return
            
            
               
            
            
              null
            
            
              ;
                              
            
            
              return
            
            
               
            
            
              null
            
            
              ;
              
               }
                          }
            
          
          
            
             }
          
        
        
          );
                    }
          
        
        
          );
          
           
          
           }
        
      
    
           你期望spring在执行完execute回调后,在关闭session的时候提交事务,想法是很好的,但spring并不会这么做.让我们来看看在Hibernate的源代码中,session.beginTransation()做了什么事。看如下代码(2):
              }
        
      
    
           你期望spring在执行完execute回调后,在关闭session的时候提交事务,想法是很好的,但spring并不会这么做.让我们来看看在Hibernate的源代码中,session.beginTransation()做了什么事。看如下代码(2): 
 
    
    
       public
      
      
         Transaction beginTransaction() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
      
      
        public
      
      
         Transaction beginTransaction() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
          
           errorIfClosed();
                  errorIfClosed();
          
           if
        
        
           ( rootSession 
        
        
          !=
        
        
           
        
        
          null
        
        
           ) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           ( rootSession 
        
        
          !=
        
        
           
        
        
          null
        
        
           ) 
        
        
        
          
            {
            
             //
          
          
             todo : should seriously consider not allowing a txn to begin from a child session
                        
          
          
            //
          
          
             todo : should seriously consider not allowing a txn to begin from a child session
            
             //
          
          
                  can always route the request to the root session
                        
          
          
            //
          
          
                  can always route the request to the root session
             
          
          
            
             log.warn( 
          
          
            "
          
          
            Transaction started on non-root session
          
          
            "
          
          
             );
          
          
                        log.warn( 
          
          
            "
          
          
            Transaction started on non-root session
          
          
            "
          
          
             );
            
             }
                    }
          
        
        
          
           Transaction result 
        
        
          =
        
        
           getTransaction();
                  Transaction result 
        
        
          =
        
        
           getTransaction();
          
           result.begin();
                  result.begin();
          
           return
        
        
           result;
                  
        
        
          return
        
        
           result;
          
           }
        
      
    
     这个方法中的result是一个org.hibernate.transaction.JDBCTransaction实例,而方法中的getTransaction()方法源代码为(3):
              }
        
      
    
     这个方法中的result是一个org.hibernate.transaction.JDBCTransaction实例,而方法中的getTransaction()方法源代码为(3): 
 
    
    
       public
      
      
         Transaction getTransaction() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
      
      
        public
      
      
         Transaction getTransaction() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
          
           if
        
        
           (hibernateTransaction
        
        
          ==
        
        
          null
        
        
          ) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (hibernateTransaction
        
        
          ==
        
        
          null
        
        
          ) 
        
        
        
          
            {
            
             log.error(owner.getFactory().getSettings()
                        log.error(owner.getFactory().getSettings()
            
             .getTransactionFactory().getClass());
                                .getTransactionFactory().getClass());
            
             hibernateTransaction 
          
          
            =
          
          
             owner.getFactory().getSettings()
                        hibernateTransaction 
          
          
            =
          
          
             owner.getFactory().getSettings()
            
             .getTransactionFactory()
                                .getTransactionFactory()
            
             .createTransaction( 
          
          
            this
          
          
            , owner );
                                .createTransaction( 
          
          
            this
          
          
            , owner );
            
             }
                    }
          
        
        
          
           return
        
        
           hibernateTransaction;
                  
        
        
          return
        
        
           hibernateTransaction;
          
           }
        
      
    
     再次追踪,owner.getFactory().getSettings() .getTransactionFactory()的createTransaction()方法源代码如下(4):
              }
        
      
    
     再次追踪,owner.getFactory().getSettings() .getTransactionFactory()的createTransaction()方法源代码如下(4): 
 
    
    
       public
      
      
         Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)
      
        public
      
      
         Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)
        
         throws
      
      
         HibernateException 
      
      
      
        
          {
        
            
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
          
           return
        
        
           
        
        
          new
        
        
           JDBCTransaction( jdbcContext, transactionContext );
                  
        
        
          return
        
        
           
        
        
          new
        
        
           JDBCTransaction( jdbcContext, transactionContext );
          
           }
        
      
    
     它返回了一个JDBCTransaction,没什么特别的。
              }
        
      
    
     它返回了一个JDBCTransaction,没什么特别的。 
 
    
在代码2中,执行了result.begin(),其实也就是JDBCTransaction实例的begin()方法,来看看(5):
    
    
       public
      
      
         
      
      
        void
      
      
         begin() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        void
      
      
         begin() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
          
           if
        
        
           (begun) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (begun) 
        
        
        
          
            {
            
             return
          
          
            ;
                        
          
          
            return
          
          
            ;
            
             }
                    }
          
        
        
          
           if
        
        
           (commitFailed) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (commitFailed) 
        
        
        
          
            {
            
             throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            cannot re-start transaction after failed commit
          
          
            "
          
          
            );
                        
          
          
            throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            cannot re-start transaction after failed commit
          
          
            "
          
          
            );
            
             }
                    }
          
        
        
          
           log.debug(
        
        
          "
        
        
          begin
        
        
          "
        
        
          );
                  log.debug(
        
        
          "
        
        
          begin
        
        
          "
        
        
          );
          
           try
        
        
           
        
        
        
          
            {
          
                  
        
        
          try
        
        
           
        
        
        
          
            {
            
             toggleAutoCommit 
          
          
            =
          
          
             jdbcContext.connection().getAutoCommit();
                        toggleAutoCommit 
          
          
            =
          
          
             jdbcContext.connection().getAutoCommit();
            
             if
          
          
             (log.isDebugEnabled()) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (log.isDebugEnabled()) 
          
          
          
            
              {
              
               log.debug(
            
            
              "
            
            
              current autocommit status: 
            
            
              "
            
            
               
            
            
              +
            
            
               toggleAutoCommit);
                              log.debug(
            
            
              "
            
            
              current autocommit status: 
            
            
              "
            
            
               
            
            
              +
            
            
               toggleAutoCommit);
              
               }
                          }
            
          
          
            
             if
          
          
             (toggleAutoCommit) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (toggleAutoCommit) 
          
          
          
            
              {
              
               log.debug(
            
            
              "
            
            
              disabling autocommit
            
            
              "
            
            
              );
                              log.debug(
            
            
              "
            
            
              disabling autocommit
            
            
              "
            
            
              );
              
               jdbcContext.connection().setAutoCommit(
            
            
              false
            
            
              );
            
            
              //
            
            
              把自动提交设为了false
                              jdbcContext.connection().setAutoCommit(
            
            
              false
            
            
              );
            
            
              //
            
            
              把自动提交设为了false
            
            
              
               }
            
            
                          }
            
          
          
            
             }
          
        
        
           
        
        
          catch
        
        
           (SQLException e) 
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          catch
        
        
           (SQLException e) 
        
        
        
          
            {
            
             log.error(
          
          
            "
          
          
            JDBC begin failed
          
          
            "
          
          
            , e);
                        log.error(
          
          
            "
          
          
            JDBC begin failed
          
          
            "
          
          
            , e);
            
             throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            JDBC begin failed: 
          
          
            "
          
          
            , e);
                        
          
          
            throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            JDBC begin failed: 
          
          
            "
          
          
            , e);
            
             }
                    }
          
        
        
          
           callback 
        
        
          =
        
        
           jdbcContext.registerCallbackIfNecessary();
                  callback 
        
        
          =
        
        
           jdbcContext.registerCallbackIfNecessary();
          
           begun 
        
        
          =
        
        
           
        
        
          true
        
        
          ;
                  begun 
        
        
          =
        
        
           
        
        
          true
        
        
          ;
          
           committed 
        
        
          =
        
        
           
        
        
          false
        
        
          ;
                  committed 
        
        
          =
        
        
           
        
        
          false
        
        
          ;
          
           rolledBack 
        
        
          =
        
        
           
        
        
          false
        
        
          ;
                  rolledBack 
        
        
          =
        
        
           
        
        
          false
        
        
          ;
          
           
          
           if
        
        
           (timeout 
        
        
          >
        
        
           
        
        
          0
        
        
          ) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (timeout 
        
        
          >
        
        
           
        
        
          0
        
        
          ) 
        
        
        
          
            {
            
             jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);
                        jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);
            
             }
                    }
          
        
        
          
           
          
           jdbcContext.afterTransactionBegin(
        
        
          this
        
        
          );
                  jdbcContext.afterTransactionBegin(
        
        
          this
        
        
          );
          
           }
              }
        
      
    
    
在直接使用Hibernate时,要在事务结束的时候,写上一句:tx.commit(),这个commit()的源码为:
    
       public
      
      
         
      
      
        void
      
      
         commit() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        void
      
      
         commit() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
          
           if
        
        
           (
        
        
          !
        
        
          begun) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (
        
        
          !
        
        
          begun) 
        
        
        
          
            {
            
             throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            Transaction not successfully started
          
          
            "
          
          
            );
                        
          
          
            throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            Transaction not successfully started
          
          
            "
          
          
            );
            
             }
                    }
          
        
        
          
           
          
           log.debug(
        
        
          "
        
        
          commit
        
        
          "
        
        
          );
                  log.debug(
        
        
          "
        
        
          commit
        
        
          "
        
        
          );
          
           
          
           if
        
        
           (
        
        
          !
        
        
          transactionContext.isFlushModeNever() 
        
        
          &&
        
        
           callback) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (
        
        
          !
        
        
          transactionContext.isFlushModeNever() 
        
        
          &&
        
        
           callback) 
        
        
        
          
            {
            
             transactionContext.managedFlush(); 
          
          
            //
          
          
             if an exception occurs during
                        transactionContext.managedFlush(); 
          
          
            //
          
          
             if an exception occurs during
            
             //
          
          
             flush, user must call
                        
          
          
            //
          
          
             flush, user must call
            
             //
          
          
             rollback()
                        
          
          
            //
          
          
             rollback()
          
          
            
             }
          
          
                    }
          
        
        
          
           
          
           notifyLocalSynchsBeforeTransactionCompletion();
                  notifyLocalSynchsBeforeTransactionCompletion();
          
           if
        
        
           (callback) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (callback) 
        
        
        
          
            {
            
             jdbcContext.beforeTransactionCompletion(
          
          
            this
          
          
            );
                        jdbcContext.beforeTransactionCompletion(
          
          
            this
          
          
            );
            
             }
                    }
          
        
        
          
           
          
           try
        
        
           
        
        
        
          
            {
          
                  
        
        
          try
        
        
           
        
        
        
          
            {
            
             commitAndResetAutoCommit();//重点代码,它的作用是提交事务,并把connection的autocommit属性恢复为true
                        commitAndResetAutoCommit();//重点代码,它的作用是提交事务,并把connection的autocommit属性恢复为true
            
             log.debug(
          
          
            "
          
          
            committed JDBC Connection
          
          
            "
          
          
            );
                        log.debug(
          
          
            "
          
          
            committed JDBC Connection
          
          
            "
          
          
            );
            
             committed 
          
          
            =
          
          
             
          
          
            true
          
          
            ;
                        committed 
          
          
            =
          
          
             
          
          
            true
          
          
            ;
            
             if
          
          
             (callback) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (callback) 
          
          
          
            
              {
              
               jdbcContext.afterTransactionCompletion(
            
            
              true
            
            
              , 
            
            
              this
            
            
              );
                              jdbcContext.afterTransactionCompletion(
            
            
              true
            
            
              , 
            
            
              this
            
            
              );
              
               }
                          }
            
          
          
            
             notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_COMMITTED);
                        notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_COMMITTED);
            
             }
          
        
        
           
        
        
          catch
        
        
           (SQLException e) 
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          catch
        
        
           (SQLException e) 
        
        
        
          
            {
            
             log.error(
          
          
            "
          
          
            JDBC commit failed
          
          
            "
          
          
            , e);
                        log.error(
          
          
            "
          
          
            JDBC commit failed
          
          
            "
          
          
            , e);
            
             commitFailed 
          
          
            =
          
          
             
          
          
            true
          
          
            ;
                        commitFailed 
          
          
            =
          
          
             
          
          
            true
          
          
            ;
            
             if
          
          
             (callback) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (callback) 
          
          
          
            
              {
              
               jdbcContext.afterTransactionCompletion(
            
            
              false
            
            
              , 
            
            
              this
            
            
              );
                              jdbcContext.afterTransactionCompletion(
            
            
              false
            
            
              , 
            
            
              this
            
            
              );
              
               }
                          }
            
          
          
            
             notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_UNKNOWN);
                        notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_UNKNOWN);
            
             throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            JDBC commit failed
          
          
            "
          
          
            , e);
                        
          
          
            throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            JDBC commit failed
          
          
            "
          
          
            , e);
            
             }
          
        
        
           
        
        
          finally
        
        
           
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          finally
        
        
           
        
        
        
          
            {
            
             closeIfRequired();
                        closeIfRequired();
            
             }
                    }
          
        
        
          
           }
              }
        
      
    
    
上面代码中,commitAndResetAutoCommit()方法的源码如下:
    
       private
      
      
         
      
      
        void
      
      
         commitAndResetAutoCommit() 
      
      
        throws
      
      
         SQLException 
      
      
      
        
          {
      
      
        private
      
      
         
      
      
        void
      
      
         commitAndResetAutoCommit() 
      
      
        throws
      
      
         SQLException 
      
      
      
        
          {
          
           try
        
        
           
        
        
        
          
            {
          
                  
        
        
          try
        
        
           
        
        
        
          
            {
            
             jdbcContext.connection().commit();//这段不用说也能理解了
                        jdbcContext.connection().commit();//这段不用说也能理解了
            
             }
          
        
        
           
        
        
          finally
        
        
           
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          finally
        
        
           
        
        
        
          
            {
            
             toggleAutoCommit();//这段的作用是恢复connection的autocommit属性为true
                        toggleAutoCommit();//这段的作用是恢复connection的autocommit属性为true
            
             }
                    }
          
        
        
          
           }
              }
        
      
    
    
上述代码的toggleAutoCommit()源代码如下:
    
       private
      
      
         
      
      
        void
      
      
         toggleAutoCommit() 
      
      
      
        
          {
      
      
            
      
      
        private
      
      
         
      
      
        void
      
      
         toggleAutoCommit() 
      
      
      
        
          {
          
           try
        
        
           
        
        
        
          
            {
          
                  
        
        
          try
        
        
           
        
        
        
          
            {
            
             if
          
          
             (toggleAutoCommit) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (toggleAutoCommit) 
          
          
          
            
              {
              
               log.debug(
            
            
              "
            
            
              re-enabling autocommit
            
            
              "
            
            
              );
                              log.debug(
            
            
              "
            
            
              re-enabling autocommit
            
            
              "
            
            
              );
              
               jdbcContext.connection().setAutoCommit(
            
            
              true
            
            
              );//这行代码的意义很明白了吧
                              jdbcContext.connection().setAutoCommit(
            
            
              true
            
            
              );//这行代码的意义很明白了吧
              
               }
                          }
            
          
          
            
             }
          
        
        
           
        
        
          catch
        
        
           (Exception sqle) 
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          catch
        
        
           (Exception sqle) 
        
        
        
          
            {
            
             log.error(
          
          
            "
          
          
            Could not toggle autocommit
          
          
            "
          
          
            , sqle);
                        log.error(
          
          
            "
          
          
            Could not toggle autocommit
          
          
            "
          
          
            , sqle);
            
             }
                    }
          
        
        
          
           }
        
      
    
           因此,如果你是直接使用hibernate,并手动管理它的session,并手动开启事务关闭事务的话,完全可以保证你的事务(好像完全是废话).
              }
        
      
    
           因此,如果你是直接使用hibernate,并手动管理它的session,并手动开启事务关闭事务的话,完全可以保证你的事务(好像完全是废话). 
 
    
但是,如果你用的是HibernateTemplate,如同源代码1一样,则不要指望spring在关闭session的时候为你提交事务(罪魁祸首就是在代码1中调用了session.flush())。因为在使用代码1时,spring中得到session的方式如下:
    
       Session session 
      
      
        =
      
      
         (entityInterceptor 
      
      
        !=
      
      
         
      
      
        null
      
      
         
      
      
        ?
      
      
         sessionFactory.openSession(entityInterceptor) : sessionFactory
      
        Session session 
      
      
        =
      
      
         (entityInterceptor 
      
      
        !=
      
      
         
      
      
        null
      
      
         
      
      
        ?
      
      
         sessionFactory.openSession(entityInterceptor) : sessionFactory
        
         .openSession());
      
    
     简单地说它就是得到了一个session,而没有对connection的autocommit()作任何操作,spring管理范围内的session所持有的connection是autocommit=true的,spring借助这个属性,在它关闭session时,提交数据库事务。,因此如果你在源代码1中加上一句话:
                        .openSession());
      
    
     简单地说它就是得到了一个session,而没有对connection的autocommit()作任何操作,spring管理范围内的session所持有的connection是autocommit=true的,spring借助这个属性,在它关闭session时,提交数据库事务。,因此如果你在源代码1中加上一句话: 
 
    
    
       public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
          
           CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
          
                  CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
            
             public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
            
                        
          
          
            public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
              
               log.info(session.connection().getAutoCommit());
            
            
              //
            
            
              打印一下事务提交方式
                              log.info(session.connection().getAutoCommit());
            
            
              //
            
            
              打印一下事务提交方式
              
               //
            
            
               保存stu1
                              
            
            
              //
            
            
               保存stu1
            
            
              
               Student stu1 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
            
            
                              Student stu1 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
              
               stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
               在数据库中,name字段不允许为null
                              stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
               在数据库中,name字段不允许为null
            
            
              
               session.save(stu1);
            
            
                              session.save(stu1);
              
               session.flush();
                              session.flush();
              
               
              
               Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
                              Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
              
               session.save(stu2);
            
            
              //
            
            
               没有设置name字段,预期会报出例外
                              session.save(stu2);
            
            
              //
            
            
               没有设置name字段,预期会报出例外
            
            
              
               session.flush();
            
            
                              session.flush();
              
               return
            
            
               
            
            
              null
            
            
              ;
                              
            
            
              return
            
            
               
            
            
              null
            
            
              ;
              
               }
                          }
            
          
          
            
             }
          
        
        
          );
                    }
          
        
        
          );
          
           
          
           }
        
      
    
          运行后,它打出的结果是true,也就是说,虽然保存stu2时会报出例外,但如果commit属性为true,则每一个到达数据库的sql语句会立即被提交。换句话说,在调用完session.save(stu1)后,调用session.flush(),会发送sql语句到数据库,再根据commit属性为true,则保存stu1的操作已经被持久到数据库了,尽管后面的一条insert语句出了问题。
              }
        
      
    
          运行后,它打出的结果是true,也就是说,虽然保存stu2时会报出例外,但如果commit属性为true,则每一个到达数据库的sql语句会立即被提交。换句话说,在调用完session.save(stu1)后,调用session.flush(),会发送sql语句到数据库,再根据commit属性为true,则保存stu1的操作已经被持久到数据库了,尽管后面的一条insert语句出了问题。 
 
    
因此,如果你想在HibernateCallback中使用session的事务,需要如下写:
    
       public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
          
           CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
          
                  CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
            
             public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
            
                        
          
          
            public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
              
               session.connection().setAutoCommit(
            
            
              false
            
            
              );
                              session.connection().setAutoCommit(
            
            
              false
            
            
              );
              
               //
            
            
              保存stu1
                              
            
            
              //
            
            
              保存stu1
            
            
              
               Student stu1
            
            
              =
            
            
              new
            
            
               Student();
            
            
                              Student stu1
            
            
              =
            
            
              new
            
            
               Student();
              
               stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
              在数据库中,name字段不允许为null
                              stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
              在数据库中,name字段不允许为null
            
            
              
               session.save(stu1);
            
            
                              session.save(stu1);
              
               session.flush();
                              session.flush();
              
               
                              
              
               Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
                              Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
              
               session.save(stu2);
            
            
              //
            
            
              没有设置name字段,预期会报出例外
                              session.save(stu2);
            
            
              //
            
            
              没有设置name字段,预期会报出例外
              
session.flush();
               session.connection().commit();
            
            
                              session.connection().commit();
              
               //
            
            
              至于session的关闭就不用我们操心了
                              
            
            
              //
            
            
              至于session的关闭就不用我们操心了
            
            
              
               return
            
            
               
            
            
              null
            
            
              ;
            
            
                              
            
            
              return
            
            
               
            
            
              null
            
            
              ;
              
               }
                          }
            
          
          
            
             }
          
        
        
          );
                    }
          
        
        
          );
          
           
          
           }
        
      
    
     运行上述代码,没问题了。至此,可能有些读者早就对代码1不满意了:为什么每次save()以后要调用flush()?这是有原因的。下面我们来看看把session.flush()去掉后会出什么问题。改掉后的代码如下:
              }
        
      
    
     运行上述代码,没问题了。至此,可能有些读者早就对代码1不满意了:为什么每次save()以后要调用flush()?这是有原因的。下面我们来看看把session.flush()去掉后会出什么问题。改掉后的代码如下: 
 
    
    
       public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[])
      
      
        public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
    
  
  如果你这样写(1):
 public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
           CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
          
                  CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
             public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
            
                        
          
          
            public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
               //
            
            
               保存stu1
                              
            
            
              //
            
            
               保存stu1
            
            
               Student stu1 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
            
            
                              Student stu1 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
               stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
               在数据库中,name字段不允许为null
                              stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
               在数据库中,name字段不允许为null
            
            
               session.save(stu1);
            
            
                              session.save(stu1);
               session.flush();//实际上,如果不是程序员"手痒"来调用这个flush(),HibernateTemplate中session的事务处理还是很方便的
                              session.flush();//实际上,如果不是程序员"手痒"来调用这个flush(),HibernateTemplate中session的事务处理还是很方便的
               
               Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
                              Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
               session.save(stu2);
            
            
              //
            
            
               没有设置name字段,预期会报出例外
                              session.save(stu2);
            
            
              //
            
            
               没有设置name字段,预期会报出例外
            
            
               session.flush();
            
            
                              session.flush();
               return
            
            
               
            
            
              null
            
            
              ;
                              
            
            
              return
            
            
               
            
            
              null
            
            
              ;
               }
                          }
            
          
          
             }
          
        
        
          );
                    }
          
        
        
          );
           
           }
              }
        
      
     public
      
      
         Transaction beginTransaction() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
      
      
        public
      
      
         Transaction beginTransaction() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
           errorIfClosed();
                  errorIfClosed();
           if
        
        
           ( rootSession 
        
        
          !=
        
        
           
        
        
          null
        
        
           ) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           ( rootSession 
        
        
          !=
        
        
           
        
        
          null
        
        
           ) 
        
        
        
          
            {
             //
          
          
             todo : should seriously consider not allowing a txn to begin from a child session
                        
          
          
            //
          
          
             todo : should seriously consider not allowing a txn to begin from a child session
             //
          
          
                  can always route the request to the root session
                        
          
          
            //
          
          
                  can always route the request to the root session
             
          
          
             log.warn( 
          
          
            "
          
          
            Transaction started on non-root session
          
          
            "
          
          
             );
          
          
                        log.warn( 
          
          
            "
          
          
            Transaction started on non-root session
          
          
            "
          
          
             );
             }
                    }
          
        
        
           Transaction result 
        
        
          =
        
        
           getTransaction();
                  Transaction result 
        
        
          =
        
        
           getTransaction();
           result.begin();
                  result.begin();
           return
        
        
           result;
                  
        
        
          return
        
        
           result;
           }
              }
        
      
     public
      
      
         Transaction getTransaction() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
      
      
        public
      
      
         Transaction getTransaction() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
           if
        
        
           (hibernateTransaction
        
        
          ==
        
        
          null
        
        
          ) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (hibernateTransaction
        
        
          ==
        
        
          null
        
        
          ) 
        
        
        
          
            {
             log.error(owner.getFactory().getSettings()
                        log.error(owner.getFactory().getSettings()
             .getTransactionFactory().getClass());
                                .getTransactionFactory().getClass());
             hibernateTransaction 
          
          
            =
          
          
             owner.getFactory().getSettings()
                        hibernateTransaction 
          
          
            =
          
          
             owner.getFactory().getSettings()
             .getTransactionFactory()
                                .getTransactionFactory()
             .createTransaction( 
          
          
            this
          
          
            , owner );
                                .createTransaction( 
          
          
            this
          
          
            , owner );
             }
                    }
          
        
        
           return
        
        
           hibernateTransaction;
                  
        
        
          return
        
        
           hibernateTransaction;
           }
              }
        
      
     public
      
      
         Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)
      
        public
      
      
         Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)
         throws
      
      
         HibernateException 
      
      
      
        
          {
        
            
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
           return
        
        
           
        
        
          new
        
        
           JDBCTransaction( jdbcContext, transactionContext );
                  
        
        
          return
        
        
           
        
        
          new
        
        
           JDBCTransaction( jdbcContext, transactionContext );
           }
              }
        
      
    在代码2中,执行了result.begin(),其实也就是JDBCTransaction实例的begin()方法,来看看(5):
 public
      
      
         
      
      
        void
      
      
         begin() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        void
      
      
         begin() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
           if
        
        
           (begun) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (begun) 
        
        
        
          
            {
             return
          
          
            ;
                        
          
          
            return
          
          
            ;
             }
                    }
          
        
        
           if
        
        
           (commitFailed) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (commitFailed) 
        
        
        
          
            {
             throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            cannot re-start transaction after failed commit
          
          
            "
          
          
            );
                        
          
          
            throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            cannot re-start transaction after failed commit
          
          
            "
          
          
            );
             }
                    }
          
        
        
           log.debug(
        
        
          "
        
        
          begin
        
        
          "
        
        
          );
                  log.debug(
        
        
          "
        
        
          begin
        
        
          "
        
        
          );
           try
        
        
           
        
        
        
          
            {
          
                  
        
        
          try
        
        
           
        
        
        
          
            {
             toggleAutoCommit 
          
          
            =
          
          
             jdbcContext.connection().getAutoCommit();
                        toggleAutoCommit 
          
          
            =
          
          
             jdbcContext.connection().getAutoCommit();
             if
          
          
             (log.isDebugEnabled()) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (log.isDebugEnabled()) 
          
          
          
            
              {
               log.debug(
            
            
              "
            
            
              current autocommit status: 
            
            
              "
            
            
               
            
            
              +
            
            
               toggleAutoCommit);
                              log.debug(
            
            
              "
            
            
              current autocommit status: 
            
            
              "
            
            
               
            
            
              +
            
            
               toggleAutoCommit);
               }
                          }
            
          
          
             if
          
          
             (toggleAutoCommit) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (toggleAutoCommit) 
          
          
          
            
              {
               log.debug(
            
            
              "
            
            
              disabling autocommit
            
            
              "
            
            
              );
                              log.debug(
            
            
              "
            
            
              disabling autocommit
            
            
              "
            
            
              );
               jdbcContext.connection().setAutoCommit(
            
            
              false
            
            
              );
            
            
              //
            
            
              把自动提交设为了false
                              jdbcContext.connection().setAutoCommit(
            
            
              false
            
            
              );
            
            
              //
            
            
              把自动提交设为了false
            
            
               }
            
            
                          }
            
          
          
             }
          
        
        
           
        
        
          catch
        
        
           (SQLException e) 
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          catch
        
        
           (SQLException e) 
        
        
        
          
            {
             log.error(
          
          
            "
          
          
            JDBC begin failed
          
          
            "
          
          
            , e);
                        log.error(
          
          
            "
          
          
            JDBC begin failed
          
          
            "
          
          
            , e);
             throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            JDBC begin failed: 
          
          
            "
          
          
            , e);
                        
          
          
            throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            JDBC begin failed: 
          
          
            "
          
          
            , e);
             }
                    }
          
        
        
           callback 
        
        
          =
        
        
           jdbcContext.registerCallbackIfNecessary();
                  callback 
        
        
          =
        
        
           jdbcContext.registerCallbackIfNecessary();
           begun 
        
        
          =
        
        
           
        
        
          true
        
        
          ;
                  begun 
        
        
          =
        
        
           
        
        
          true
        
        
          ;
           committed 
        
        
          =
        
        
           
        
        
          false
        
        
          ;
                  committed 
        
        
          =
        
        
           
        
        
          false
        
        
          ;
           rolledBack 
        
        
          =
        
        
           
        
        
          false
        
        
          ;
                  rolledBack 
        
        
          =
        
        
           
        
        
          false
        
        
          ;
           
           if
        
        
           (timeout 
        
        
          >
        
        
           
        
        
          0
        
        
          ) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (timeout 
        
        
          >
        
        
           
        
        
          0
        
        
          ) 
        
        
        
          
            {
             jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);
                        jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);
             }
                    }
          
        
        
           
           jdbcContext.afterTransactionBegin(
        
        
          this
        
        
          );
                  jdbcContext.afterTransactionBegin(
        
        
          this
        
        
          );
           }
              }
        
      
    在直接使用Hibernate时,要在事务结束的时候,写上一句:tx.commit(),这个commit()的源码为:
 public
      
      
         
      
      
        void
      
      
         commit() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        void
      
      
         commit() 
      
      
        throws
      
      
         HibernateException 
      
      
      
        
          {
           if
        
        
           (
        
        
          !
        
        
          begun) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (
        
        
          !
        
        
          begun) 
        
        
        
          
            {
             throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            Transaction not successfully started
          
          
            "
          
          
            );
                        
          
          
            throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            Transaction not successfully started
          
          
            "
          
          
            );
             }
                    }
          
        
        
           
           log.debug(
        
        
          "
        
        
          commit
        
        
          "
        
        
          );
                  log.debug(
        
        
          "
        
        
          commit
        
        
          "
        
        
          );
           
           if
        
        
           (
        
        
          !
        
        
          transactionContext.isFlushModeNever() 
        
        
          &&
        
        
           callback) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (
        
        
          !
        
        
          transactionContext.isFlushModeNever() 
        
        
          &&
        
        
           callback) 
        
        
        
          
            {
             transactionContext.managedFlush(); 
          
          
            //
          
          
             if an exception occurs during
                        transactionContext.managedFlush(); 
          
          
            //
          
          
             if an exception occurs during
             //
          
          
             flush, user must call
                        
          
          
            //
          
          
             flush, user must call
             //
          
          
             rollback()
                        
          
          
            //
          
          
             rollback()
          
          
             }
          
          
                    }
          
        
        
           
           notifyLocalSynchsBeforeTransactionCompletion();
                  notifyLocalSynchsBeforeTransactionCompletion();
           if
        
        
           (callback) 
        
        
        
          
            {
          
                  
        
        
          if
        
        
           (callback) 
        
        
        
          
            {
             jdbcContext.beforeTransactionCompletion(
          
          
            this
          
          
            );
                        jdbcContext.beforeTransactionCompletion(
          
          
            this
          
          
            );
             }
                    }
          
        
        
           
           try
        
        
           
        
        
        
          
            {
          
                  
        
        
          try
        
        
           
        
        
        
          
            {
             commitAndResetAutoCommit();//重点代码,它的作用是提交事务,并把connection的autocommit属性恢复为true
                        commitAndResetAutoCommit();//重点代码,它的作用是提交事务,并把connection的autocommit属性恢复为true
             log.debug(
          
          
            "
          
          
            committed JDBC Connection
          
          
            "
          
          
            );
                        log.debug(
          
          
            "
          
          
            committed JDBC Connection
          
          
            "
          
          
            );
             committed 
          
          
            =
          
          
             
          
          
            true
          
          
            ;
                        committed 
          
          
            =
          
          
             
          
          
            true
          
          
            ;
             if
          
          
             (callback) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (callback) 
          
          
          
            
              {
               jdbcContext.afterTransactionCompletion(
            
            
              true
            
            
              , 
            
            
              this
            
            
              );
                              jdbcContext.afterTransactionCompletion(
            
            
              true
            
            
              , 
            
            
              this
            
            
              );
               }
                          }
            
          
          
             notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_COMMITTED);
                        notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_COMMITTED);
             }
          
        
        
           
        
        
          catch
        
        
           (SQLException e) 
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          catch
        
        
           (SQLException e) 
        
        
        
          
            {
             log.error(
          
          
            "
          
          
            JDBC commit failed
          
          
            "
          
          
            , e);
                        log.error(
          
          
            "
          
          
            JDBC commit failed
          
          
            "
          
          
            , e);
             commitFailed 
          
          
            =
          
          
             
          
          
            true
          
          
            ;
                        commitFailed 
          
          
            =
          
          
             
          
          
            true
          
          
            ;
             if
          
          
             (callback) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (callback) 
          
          
          
            
              {
               jdbcContext.afterTransactionCompletion(
            
            
              false
            
            
              , 
            
            
              this
            
            
              );
                              jdbcContext.afterTransactionCompletion(
            
            
              false
            
            
              , 
            
            
              this
            
            
              );
               }
                          }
            
          
          
             notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_UNKNOWN);
                        notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_UNKNOWN);
             throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            JDBC commit failed
          
          
            "
          
          
            , e);
                        
          
          
            throw
          
          
             
          
          
            new
          
          
             TransactionException(
          
          
            "
          
          
            JDBC commit failed
          
          
            "
          
          
            , e);
             }
          
        
        
           
        
        
          finally
        
        
           
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          finally
        
        
           
        
        
        
          
            {
             closeIfRequired();
                        closeIfRequired();
             }
                    }
          
        
        
           }
              }
        
      
    上面代码中,commitAndResetAutoCommit()方法的源码如下:
 private
      
      
         
      
      
        void
      
      
         commitAndResetAutoCommit() 
      
      
        throws
      
      
         SQLException 
      
      
      
        
          {
      
      
        private
      
      
         
      
      
        void
      
      
         commitAndResetAutoCommit() 
      
      
        throws
      
      
         SQLException 
      
      
      
        
          {
           try
        
        
           
        
        
        
          
            {
          
                  
        
        
          try
        
        
           
        
        
        
          
            {
             jdbcContext.connection().commit();//这段不用说也能理解了
                        jdbcContext.connection().commit();//这段不用说也能理解了
             }
          
        
        
           
        
        
          finally
        
        
           
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          finally
        
        
           
        
        
        
          
            {
             toggleAutoCommit();//这段的作用是恢复connection的autocommit属性为true
                        toggleAutoCommit();//这段的作用是恢复connection的autocommit属性为true
             }
                    }
          
        
        
           }
              }
        
      
    上述代码的toggleAutoCommit()源代码如下:
 private
      
      
         
      
      
        void
      
      
         toggleAutoCommit() 
      
      
      
        
          {
      
      
            
      
      
        private
      
      
         
      
      
        void
      
      
         toggleAutoCommit() 
      
      
      
        
          {
           try
        
        
           
        
        
        
          
            {
          
                  
        
        
          try
        
        
           
        
        
        
          
            {
             if
          
          
             (toggleAutoCommit) 
          
          
          
            
              {
            
                        
          
          
            if
          
          
             (toggleAutoCommit) 
          
          
          
            
              {
               log.debug(
            
            
              "
            
            
              re-enabling autocommit
            
            
              "
            
            
              );
                              log.debug(
            
            
              "
            
            
              re-enabling autocommit
            
            
              "
            
            
              );
               jdbcContext.connection().setAutoCommit(
            
            
              true
            
            
              );//这行代码的意义很明白了吧
                              jdbcContext.connection().setAutoCommit(
            
            
              true
            
            
              );//这行代码的意义很明白了吧
               }
                          }
            
          
          
             }
          
        
        
           
        
        
          catch
        
        
           (Exception sqle) 
        
        
        
          
            {
            
                    }
          
        
        
           
        
        
          catch
        
        
           (Exception sqle) 
        
        
        
          
            {
             log.error(
          
          
            "
          
          
            Could not toggle autocommit
          
          
            "
          
          
            , sqle);
                        log.error(
          
          
            "
          
          
            Could not toggle autocommit
          
          
            "
          
          
            , sqle);
             }
                    }
          
        
        
           }
              }
        
      
    但是,如果你用的是HibernateTemplate,如同源代码1一样,则不要指望spring在关闭session的时候为你提交事务(罪魁祸首就是在代码1中调用了session.flush())。因为在使用代码1时,spring中得到session的方式如下:
 Session session 
      
      
        =
      
      
         (entityInterceptor 
      
      
        !=
      
      
         
      
      
        null
      
      
         
      
      
        ?
      
      
         sessionFactory.openSession(entityInterceptor) : sessionFactory
      
        Session session 
      
      
        =
      
      
         (entityInterceptor 
      
      
        !=
      
      
         
      
      
        null
      
      
         
      
      
        ?
      
      
         sessionFactory.openSession(entityInterceptor) : sessionFactory
         .openSession());
                        .openSession());
      
     public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
           CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
          
                  CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
             public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
            
                        
          
          
            public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
               log.info(session.connection().getAutoCommit());
            
            
              //
            
            
              打印一下事务提交方式
                              log.info(session.connection().getAutoCommit());
            
            
              //
            
            
              打印一下事务提交方式
               //
            
            
               保存stu1
                              
            
            
              //
            
            
               保存stu1
            
            
               Student stu1 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
            
            
                              Student stu1 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
               stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
               在数据库中,name字段不允许为null
                              stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
               在数据库中,name字段不允许为null
            
            
               session.save(stu1);
            
            
                              session.save(stu1);
               session.flush();
                              session.flush();
               
               Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
                              Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
               session.save(stu2);
            
            
              //
            
            
               没有设置name字段,预期会报出例外
                              session.save(stu2);
            
            
              //
            
            
               没有设置name字段,预期会报出例外
            
            
               session.flush();
            
            
                              session.flush();
               return
            
            
               
            
            
              null
            
            
              ;
                              
            
            
              return
            
            
               
            
            
              null
            
            
              ;
               }
                          }
            
          
          
             }
          
        
        
          );
                    }
          
        
        
          );
           
           }
              }
        
      
    因此,如果你想在HibernateCallback中使用session的事务,需要如下写:
 public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
      
      
        public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
      
        
          {
           CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
          
                  CtxUtil.getBaseManager().getHibernateTemplate().execute(
        
        
          new
        
        
           HibernateCallback() 
        
        
        
          
            {
             public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
            
                        
          
          
            public
          
          
             Object doInHibernate(Session session) 
          
          
            throws
          
          
             HibernateException, SQLException 
          
          
          
            
              {
               session.connection().setAutoCommit(
            
            
              false
            
            
              );
                              session.connection().setAutoCommit(
            
            
              false
            
            
              );
               //
            
            
              保存stu1
                              
            
            
              //
            
            
              保存stu1
            
            
               Student stu1
            
            
              =
            
            
              new
            
            
               Student();
            
            
                              Student stu1
            
            
              =
            
            
              new
            
            
               Student();
               stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
              在数据库中,name字段不允许为null
                              stu1.setName(
            
            
              "
            
            
              aaaa
            
            
              "
            
            
              );
            
            
              //
            
            
              在数据库中,name字段不允许为null
            
            
               session.save(stu1);
            
            
                              session.save(stu1);
               session.flush();
                              session.flush();
               
                              
               Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
                              Student stu2 
            
            
              =
            
            
               
            
            
              new
            
            
               Student();
               session.save(stu2);
            
            
              //
            
            
              没有设置name字段,预期会报出例外
                              session.save(stu2);
            
            
              //
            
            
              没有设置name字段,预期会报出例外
              session.flush();
 session.connection().commit();
            
            
                              session.connection().commit();
               //
            
            
              至于session的关闭就不用我们操心了
                              
            
            
              //
            
            
              至于session的关闭就不用我们操心了
            
            
               return
            
            
               
            
            
              null
            
            
              ;
            
            
                              
            
            
              return
            
            
               
            
            
              null
            
            
              ;
               }
                          }
            
          
          
             }
          
        
        
          );
                    }
          
        
        
          );
           
           }
              }
        
      
     public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[])
      
      
        public
      
      
         
      
      
        static
      
      
         
      
      
        void
      
      
         main(String ss[]) 
      
      
    
(转载


 
       CtxUtil.getBaseManager().getHibernateTemplate().execute(
                  CtxUtil.getBaseManager().getHibernateTemplate().execute(
         
					 
					