熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

Hibernate 基於JDBC的事務

2013-11-23 20:36:23  來源: Java開源技術 

  Hibernate 是JDBC 的輕量級封裝本身並不具備事務管理能力在事務管理層Hibernate將其委托給底層的JDBC或者JTA以實現事務管理和調度功能

  Hibernate的默認事務處理機制基於JDBC Transaction我們也可以通過配置文件設定采用JTA作為事務管理實現

  Java代碼





    <hibernateconfiguration>   
    <sessionfactory>   
    ……   
    <property name=hibernatetransactionfactory_class>   
    netsfhibernatetransactionJTATransactionFactory   
    <!netsfhibernatetransactionJDBCTransactionFactory>   
    </property>   
    ……   
    </sessionfactory>   
    </hibernateconfiguration>  

  <hibernateconfiguration> <sessionfactory> …… <property name=hibernatetransactionfactory_class> netsfhibernatetransactionJTATransactionFactory <!netsfhibernatetransactionJDBCTransactionFactory> </property> …… </sessionfactory> </hibernateconfiguration>


基於JDBC的事務管理將事務管理委托給JDBC 進行處理無疑是最簡單的實現方式Hibernate 對於JDBC事務的封裝也極為簡單
我們來看下面這段代碼



Java代碼

    session = sessionFactoryopenSession();   
    Transaction tx = sessionbeginTransaction();   
    ……   
    mit();  

  session = sessionFactoryopenSession(); Transaction tx = sessionbeginTransaction(); …… mit();


從JDBC層面而言上面的代碼實際上對應著



Java代碼

    Connection dbconn = getConnection();   
    dbconnsetAutoCommit(false);   
    ……   
    mit();  

  Connection dbconn = getConnection(); dbconnsetAutoCommit(false); …… mit();


就是這麼簡單Hibernate並沒有做更多的事情(實際上也沒法做更多的事情)只是將這樣的JDBC代碼進行了封裝而已
這裡要注意的是在sessionFactoryopenSession()中hibernate會初始化數據庫連接與此同時將其AutoCommit 設為關閉狀態(false)而其後在SessionbeginTransaction 方法中Hibernate 會再次確認Connection 的AutoCommit 屬性被設為關閉狀態( 為了防止用戶代碼對session 的ConnectionAutoCommit屬性進行修改)
這也就是說我們一開始從SessionFactory獲得的session其自動提交屬性就已經被關閉(AutoCommit=false)下面的代碼將不會對數據庫產生任何效果



Java代碼

    session = sessionFactoryopenSession();   
    sessionsave(user);   
    sessionclose();  

  session = sessionFactoryopenSession(); sessionsave(user); sessionclose();


這實際上相當於 JDBC Connection的AutoCommit屬性被設為false執行了若干JDBC操作之後沒有調用commit操作即將Connection關閉如果要使代碼真正作用到數據庫我們必須顯式的調用Transaction指令



Java代碼

    session = sessionFactoryopenSession();   
    Transaction tx = sessionbeginTransaction();   
    sessionsave(user);   
    mit();   
    sessionclose();  

  session = sessionFactoryopenSession(); Transaction tx = sessionbeginTransaction(); sessionsave(user); mit(); sessionclose();


基於JTA的事務管理
JTA 提供了跨Session 的事務管理能力這一點是與JDBC Transaction 最大的差異
JDBC事務由Connnection管理也就是說事務管理實際上是在JDBC Connection中實現事務周期限於Connection的生命周期之類同樣對於基於JDBC Transaction的Hibernate 事務管理機制而言事務管理在Session 所依托的JDBC Connection中實現事務周期限於Session的生命周期
JTA 事務管理則由 JTA 容器實現JTA 容器對當前加入事務的眾多Connection 進
行調度實現其事務性要求JTA的事務周期可橫跨多個JDBC Connection生命周期
同樣對於基於JTA事務的Hibernate而言JTA事務橫跨可橫跨多個Session
JTA 事務是由JTA Container 維護而參與事務的Connection無需對事務管理進行干涉這也就是說如果采用JTA Transaction我們不應該再調用HibernateTransaction功能
上面基於JDBC Transaction的正確代碼這裡就會產生問題



Java代碼

    public class ClassA{   
    public void saveUser(User user){   
    session = sessionFactoryopenSession();   
    Transaction tx = sessionbeginTransaction();   
    sessionsave(user);   
    mit();   
    sessionclose();   
    }   
    }   
    public class ClassB{   
    public void saveOrder(Order order){   
    session = sessionFactoryopenSession();   
    Transaction tx = sessionbeginTransaction();   
    sessionsave(order);   
    mit();   
    sessionclose();   
    }   
    }   
    public class ClassC{   
    public void save(){   
    ……   
    UserTransaction tx = new InitialContext()lookup(……);   
    ClassAsave(user);   
    ClassBsave(order);   
    mit();   
    ……   
    }   
    }  

  public class ClassA{ public void saveUser(User user){ session = sessionFactoryopenSession(); Transaction tx = sessionbeginTransaction(); sessionsave(user); mit(); sessionclose(); } } public class ClassB{ public void saveOrder(Order order){ session = sessionFactoryopenSession(); Transaction tx = sessionbeginTransaction(); sessionsave(order); mit(); sessionclose(); } } public class ClassC{ public void save(){ …… UserTransaction tx = new InitialContext()lookup(……); ClassAsave(user); ClassBsave(order); mit(); …… } }

這裡有兩個類ClassA和ClassB分別提供了兩個方法saveUsersaveOrder
用於保存用戶信息和訂單信息在ClassC中我們接連調用了ClassAsaveUser方法和ClassBsaveOrder 方法同時引入了JTA 中的UserTransaction 以實現ClassCsave方法中的事務性問題出現了ClassA 和ClassB 中分別都調用了Hibernate 的Transaction 功能在Hibernate 的JTA 封裝中SessionbeginTransaction 同樣也執行了InitialContextlookup方法獲取UserTransaction實例mit方法同樣也調用了mit方法實際上這就形成了兩個嵌套式的JTA TransactionClassC 申明了一個事務而在ClassC 事務周期內ClassA 和ClassB也企圖申明自己的事務這將導致運行期錯誤因此如果決定采用JTA Transaction應避免再重復調用Hibernate 的
Transaction功能上面的代碼修改如下



Java代碼

    public class ClassA{   
    public void save(TUser user){   
    session = sessionFactoryopenSession();   
    sessionsave(user);   
    sessionclose();   
    }   
    ……   
    }   
    public class ClassB{   
    public void save (Order order){   
    session = sessionFactoryopenSession();   
    sessionsave(order);   
    sessionclose();   
    }   
    ……   
    }   
    public class ClassC{   
    public void save(){   
    ……   
    UserTransaction tx = new InitialContext()lookup(……);   
    classAsave(user);   
    classBsave(order);   
    mit();   
    ……   
    }   
    }  

  public class ClassA{ public void save(TUser user){ session = sessionFactoryopenSession(); sessionsave(user); sessionclose(); } …… } public class ClassB{ public void save (Order order){ session = sessionFactoryopenSession(); sessionsave(order); sessionclose(); } …… } public class ClassC{ public void save(){ …… UserTransaction tx = new InitialContext()lookup(……); classAsave(user); classBsave(order); mit(); …… } }


上面代碼中的ClassCsave方法也可以改成這樣



Java代碼

    public class ClassC{   
    public void save(){   
    ……   
    session = sessionFactoryopenSession();   
    Transaction tx = sessionbeginTransaction();   
    classAsave(user);   
    classBsave(order);   
    mit();   
    ……   
    }   
    }  

  public class ClassC{ public void save(){ …… session = sessionFactoryopenSession(); Transaction tx = sessionbeginTransaction(); classAsave(user); classBsave(order); mit(); …… } }


實際上這是利用Hibernate來完成啟動和提交UserTransaction的功能但這樣的做法比原本直接通過InitialContext獲取UserTransaction 的做法消耗了更多的資源得不償失
在EJB 中使用JTA Transaction 無疑最為簡便我們只需要將save 方法配置為JTA事務支持即可無需顯式申明任何事務下面是一個Session Bean的save方法它的事務屬性被申明為RequiredEJB容器將自動維護此方法執行過程中的事務



Java代碼

    /**  
    * @ejbinterfacemethod  
    * viewtype=remote  
    *  
    * @ejbtransaction type = Required  
    **/  
    public void save(){   
    //EJB環境中通過部署配置即可實現事務申明而無需顯式調用事務   
    classAsave(user);   
    classBsave(log);   
    }//方法結束時如果沒有異常發生則事務由EJB容器自動提交

From:http://tw.wingwit.com/Article/program/Java/ky/201311/28740.html
  • 上一篇文章:

  • 下一篇文章:
  • Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.