Hibernate的事务管理源码

User类:

  1. public class User implements Serializable{  
  2.     public User(){}  
  3.       
  4.     private Integer id;  
  5.     private String name;  
  6.     private Integer age;  
  7.     private static final long serialVersionUID = 1L;  
  8.       
  9.     public Integer getId() {  
  10.         return id;  
  11.     }  
  12.       
  13.     public void setId(Integer id) {  
  14.         this.id = id;  
  15.     }  
  16.       
  17.     public String getName() {  
  18.         return name;  
  19.     }  
  20.       
  21.     public void setName(String name) {  
  22.         this.name = name;  
  23.     }  
  24.       
  25.     public Integer getAge() {  
  26.         return age;  
  27.     }  
  28.       
  29.     public void setAge(Integer age) {  
  30.         this.age = age;  
  31.     }  
  32. }  

User.hbm.xml:

  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC  
  3.         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  4.         "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >  
  5.   
  6. <hibernate-mapping>  
  7.     <class name="com.po.User"   
  8.         table="TEST_USER">  
  9.         <id name="id" column="id" type="java.lang.Integer">  
  10.             <generator class="assigned"/>  
  11.         </id>  
  12.         <property name="name"  
  13.                 column="name"  
  14.                 type="java.lang.String"  
  15.                 not-null="true"  
  16.                 unique="true"  
  17.                 length="20"/>  
  18.         <property name="age"  
  19.                 column="age"  
  20.                 type="java.lang.Integer"  
  21.                 not-null="true"  
  22.                 unique="false"  
  23.                 length="0"/>  
  24.     </class>  
  25. </hibernate-mapping>  

hibernate.cfg.xml:

  1. <?xml version='1.0' encoding='utf-8'?>  
  2. <!DOCTYPE hibernate-configuration PUBLIC  
  3.         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
  4.         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
  5.   
  6. <hibernate-configuration>  
  7.     <session-factory>  
  8.         <property name="show_sql">true</property>  
  9.           
  10.         <property name="hibernate.connection.driver_class">  
  11.             oracle.jdbc.driver.OracleDriver  
  12.         </property>  
  13.         <property name="hibernate.connection.url">  
  14.             jdbc:oracle:thin:@192.168.58.1:1521:123  
  15.         </property>  
  16.         <property name="hibernate.connection.username">123</property>  
  17.         <property name="hibernate.connection.password">123</property>  
  18.         <property name="dialect">org.hibernate.dialect.OracleDialect</property>  
  19.           
  20.         <mapping resource="com/po/User.hbm.xml"/>  
  21.     </session-factory>  
  22. </hibernate-configuration>  

测试类:

  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.         User user = new User();  
  4.         user.setId(1);  
  5.         user.setName("111");  
  6.         user.setAge(10);  
  7.         Configuration conf = new Configuration().configure();  
  8.         SessionFactory sf = conf.buildSessionFactory();  
  9.         Session sess = sf.openSession();  
  10.         Transaction t = sess.beginTransaction();//说明一  
  11.         try{  
  12.             sess.save(user);  
  13.             t.commit();//说明二  
  14.         }catch(Exception e){  
  15.             t.rollback();  
  16.         }finally{  
  17.             if(sess.isOpen()){  
  18.                 sess.close();  
  19.             }  
  20.         }  
  21.     }  
  22. }  

说明一:Hibernate本身没有实现自己的事务管理功能,而是对底层JDBC事务或JTA事务的轻量级封装

org.hibernate.impl.SessionImpl类(该类是会话的实现类):

  1. public Transaction beginTransaction() throws HibernateException {  
  2.        errorIfClosed();  
  3.     if ( rootSession != null ) {  
  4.        log.warn( "Transaction started on non-root session" );  
  5.     }  
  6.     Transaction result = getTransaction();  
  7.     result.begin();  
  8.     return result;  
  9. }  
  10.    
  11. public Transaction getTransaction() throws HibernateException {  
  12.     errorIfClosed();  
  13.     return jdbcContext.getTransaction();  
  14. }  

org.hibernate.jdbc.JDBCContext类:

  1. public Transaction getTransaction() throws HibernateException {  
  2.     if (hibernateTransaction==null) {  
  3.        hibernateTransaction = owner.getFactory().getSettings()  
  4.               .getTransactionFactory().createTransaction( this, owner );  
  5.     }  
  6.     return hibernateTransaction;  
  7. }  

TransactionFactory有很多实现类:

选择最基本的org.hibernate.transaction.JDBCTransactionFactory观察一下:

  1. public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)throws HibernateException {  
  2.     return new JDBCTransaction( jdbcContext, transactionContext );  
  3. }  

org.hibernate.transaction.JDBCTransaction类的说明:

  1. Transaction implementation based on transaction management through a JDBC Connection.  
  2. This the Hibernate's default transaction strategy.  

事务开始时,会禁用自动提交:

  1. public void begin() throws HibernateException {  
  2.     if (begun) {  
  3.         return;  
  4.     }  
  5.     if (commitFailed) {  
  6.         throw new TransactionException("cannot re-start transaction after failed commit");  
  7.     }  
  8.   
  9.     log.debug("begin");  
  10.   
  11.     try {  
  12.         toggleAutoCommit = jdbcContext.connection().getAutoCommit();  
  13.         if ( log.isDebugEnabled() ) {  
  14.             log.debug("current autocommit status: " + toggleAutoCommit);  
  15.         }  
  16.         if (toggleAutoCommit) {  
  17.             log.debug("disabling autocommit");  
  18.             jdbcContext.connection().setAutoCommit(false);//关闭事务自动提交  
  19.         }  
  20.     }  
  21.     catch (SQLException e) {  
  22.         log.error("JDBC begin failed", e);  
  23.         throw new TransactionException("JDBC begin failed: ", e);  
  24.     }  
  25.   
  26.     callback = jdbcContext.registerCallbackIfNecessary();  
  27.   
  28.     begun = true;  
  29.     committed = false;  
  30.     rolledBack = false;  
  31.   
  32.     if ( timeout>0 ) {  
  33.         jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);  
  34.     }  
  35.   
  36.     jdbcContext.afterTransactionBegin(this);  
  37. }  

打开log日志也能看出很多端倪:

  1. [2013-08-09 16:37:55] DEBUG  -> begin  
  2. [2013-08-09 16:37:55] DEBUG  -> opening JDBC connection  
  3. [2013-08-09 16:37:55] DEBUG  -> current autocommit status: false  
  4. [2013-08-09 16:37:55] DEBUG  -> generated identifier: 1, using strategy: org.hibernate.id.Assigned  
  5. [2013-08-09 16:37:55] DEBUG  -> commit  

说明二不需要显式的调用flush()方法,事务提交时会根据session的FlushMode自动触发session的flush

还是通过最基本的JDBCTransaction类看一下:

事务提交完成之后又恢复了事务的自动提交

  1. public void commit() throws HibernateException {  
  2.     if (!begun) {  
  3.         throw new TransactionException("Transaction not successfully started");  
  4.     }  
  5.   
  6.     log.debug("commit");  
  7.   
  8.     if ( !transactionContext.isFlushModeNever() && callback ) {  
  9.         transactionContext.managedFlush(); //根据FlushMode(通常为AUTO)刷新Session  
  10.   
  11.     notifySynchronizationsBeforeTransactionCompletion();  
  12.     if ( callback ) {  
  13.         jdbcContext.beforeTransactionCompletion( this );  
  14.     }  
  15.   
  16.     try {  
  17.         commitAndResetAutoCommit();//在该方法中重新开启了事务自动提交  
  18.         log.debug("committed JDBC Connection");  
  19.         committed = true;  
  20.         if ( callback ) {  
  21.             jdbcContext.afterTransactionCompletion( true, this );  
  22.         }  
  23.         notifySynchronizationsAfterTransactionCompletion( Status.STATUS_COMMITTED );  
  24.     }  
  25.     catch (SQLException e) {  
  26.         log.error("JDBC commit failed", e);  
  27.         commitFailed = true;  
  28.         if ( callback ) {  
  29.             jdbcContext.afterTransactionCompletion( false, this );  
  30.         }  
  31.         notifySynchronizationsAfterTransactionCompletion( Status.STATUS_UNKNOWN );  
  32.         throw new TransactionException("JDBC commit failed", e);  
  33.     }  
  34.     finally {  
  35.         closeIfRequired();  
  36.     }  
  37. }  
  38.   
  39. private void commitAndResetAutoCommit() throws SQLException {  
  40.     try {  
  41.         jdbcContext.connection().commit();  
  42.     }  
  43.     finally {  
  44.         toggleAutoCommit();  
  45.     }  
  46. }  
  47.   
  48. private void toggleAutoCommit() {  
  49.     try {  
  50.         if (toggleAutoCommit) {  
  51.             log.debug("re-enabling autocommit");  
  52.             jdbcContext.connection().setAutoCommit( true );//重新开启事务自动提交  
  53.         }  
  54.     }  
  55.     catch (Exception sqle) {  
  56.         log.error("Could not toggle autocommit", sqle);  
  57.         //swallow it (the transaction _was_ successful or successfully rolled back)  
  58.     }  
  59. }  

JDBC事务默认自动提交,但是如果Hibernate的事务策略使用JDBC,在事务开始之前,Hibernate会关闭事务自动提交,在事务结束之后,重新开启事务自动提交

posted @ 2016-03-20 11:55  浮生若云  阅读(445)  评论(0)    收藏  举报