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

分析Hibernate的事務處理機制

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

  Hibernate是對JDBC的輕量級對象封裝Hibernate本身是不具備Transaction處理功能的Hibernate的Transaction實際上是底層的JDBC Transaction的封裝或者是JTA Transaction的封裝下面我們詳細的分析
  
  Hibernate可以配置為JDBCTransaction或者是JTATransaction這取決於你在hibernateproperties中的配置:
  
  #hibernatetransactionfactory_class
  netsfhibernatetransactionJTATransactionFactory
  #hibernatetransactionfactory_class
  netsfhibernatetransactionJDBCTransactionFactory
  
  如果你什麼都不配置默認情況下使用JDBCTransaction如果你配置為
  
  hibernatetransactionfactory_class
  netsfhibernatetransactionJTATransactionFactory
  
  將使用JTATransaction不管你准備讓Hibernate使用JDBCTransaction還是JTATransaction我的忠告就是什麼都不配將讓它保持默認狀態如下
  
  #hibernatetransactionfactory_class
  netsfhibernatetransactionJTATransactionFactory
  #hibernatetransactionfactory_class
  netsfhibernatetransactionJDBCTransactionFactory
  
  在下面的分析中我會給出原因
  
  JDBC Transaction
  
  看看使用JDBC Transaction的時候我們的代碼例子
  
  Session session = sfopenSession();
  Transaction tx = sessionbeginTransactioin();
  
  sessionflush();
  mit();
  sessionclose();
  
  這是默認的情況當你在代碼中使用Hibernate的Transaction的時候實際上就是JDBCTransaction那麼JDBCTransaction究竟是什麼東西呢?來看看源代碼就清楚了
  
  Hibernate源代碼中的類
  
  netsfhibernatetransactionJDBCTransaction:
  
  public void begin() throws HibernateException {
  
  if (toggleAutoCommit) nnection()setAutoCommit(false);
  
  }
  
  這是啟動Transaction的方法看到 connection()setAutoCommit(false) 了嗎?是不是很熟悉?
  
  再來看
  
  public void commit() throws HibernateException {
  
  try {
  if ( sessiongetFlushMode()!=FlushModeNEVER ) sessionflush();
  try {
  nnection(mit();
  committed = true;
  }
  
  toggleAutoCommit();
  }
  
  這是提交方法看到connection(mit() 了嗎?下面就不用我多說了這個類代碼非常簡單易懂通過閱讀使我們明白Hibernate的Transaction都在干了些什麼?我現在把用Hibernate寫的例子翻譯成JDBC大家就一目了然了
  
  Connection conn = ; < session = sfopenSession();
  connsetAutoCommit(false); < tx = sessionbeginTransactioin();
   <
  mit(); < mit(); (對應左邊的兩句)
  connsetAutoCommit(true);
  connclose(); < sessionclose();
  
  看明白了吧Hibernate的JDBCTransaction根本就是mit而已根本毫無神秘可言只不過在Hibernate中Session打開的時候就會自動connsetAutoCommit(false)不像一般的JDBC默認都是true所以你最後不寫commit也沒有關系由於Hibernate已經把AutoCommit給關掉了所以用Hibernate的時候你在程序中不寫Transaction的話數據庫根本就沒有反應
  
  JTATransaction
  
  如果你在EJB中使用Hibernate或者准備用JTA來管理跨Session的長事務那麼就需要使用JTATransaction先看一個例子
  
  javaxtransactionUserTransaction tx = new
  InitialContext()lookup(javaxtransactionUserTransaction);
  Session s = sfopenSession();
  
  sflush();
  sclose();
  
  Session s = sfopenSession();
  
  sflush();
  sclose();
  mit();
  
  這是標准的使用JTA的代碼片斷Transaction是跨Session的它的生命周期比Session要長如果你在EJB中使用Hibernate那麼是最簡單不過的了你什麼Transaction代碼統統都不要寫了直接在EJB的部署描述符上配置某某方法是否使用事務就可以了
  
  現在我們來分析一下JTATransaction的源代碼 netsfhibernatetransactionJTATransaction:
  
  public void begin(InitialContext context
  
  ut = (UserTransaction) contextlookup(utName);
  
  
  看清楚了嗎? 和我上面寫的代碼 tx = new Initial Context?()lookup(javaxtransactionUserTransaction); 是不是完全一樣?
  
  public void commit()
  
  if (newTransaction) mit();
  
  
  JTATransaction的控制稍微復雜不過仍然可以很清楚的看出來Hibernate是如何封裝JTA的Transaction代碼的
  
  但是你現在是否看到了什麼問題? 仔細想一下Hibernate Transaction是從Session中獲得的tx = sessionbeginTransaction()最後要先提交tx然後再sessionclose這完全符合JDBC的Transaction的操作順序但是這個順序是和JTA的Transactioin操作順序徹底矛盾的!!! JTA是先啟動Transaction然後啟動Session關閉Session最後提交Transaction因此當你使用JTA的Transaction的時候那麼就千萬不要使用Hibernate的Transaction而是應該像我上面的JTA的代碼片斷那樣使用才行
  
  總結
  
  在JDBC上使用Hibernate 必須寫上Hibernate Transaction代碼否則數據庫沒有反應此時Hibernate的Transaction就是mit而已
  
  在JTA上使用Hibernate 寫JTA的Transaction代碼不要寫Hibernate的Transaction代碼否則程序會報錯
  
  在EJB上使用Hibernate 什麼Transactioin代碼都不要寫在EJB的部署描述符裡面配置
  
  |CMT(Container Managed Transaction)
  |
  |BMT(Bean Managed Transaction)
  |
  |JDBC Transaction
  |
  |JTA Transaction
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28725.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.