自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Hibernate數(shù)據(jù)庫事務攻略

開發(fā) 后端
Hibernate數(shù)據(jù)庫事務的聲明總是必須的。在Hibernate數(shù)據(jù)庫事務之外,就無法和數(shù)據(jù)庫通訊(這可能會讓那些習慣于 自動提交事務模式的開發(fā)人員感到迷惑)。

Hibernate數(shù)據(jù)庫事務有很多值得學習的地方,這里我們主要介紹Hibernate數(shù)據(jù)庫事務聲明,包括介紹 非托管環(huán)境、使用JTA、異常處理等方面。

Hibernate數(shù)據(jù)庫事務聲明

數(shù)據(jù)庫(或者系統(tǒng))事務的聲明總是必須的。在數(shù)據(jù)庫事務之外,就無法和數(shù)據(jù)庫通訊(這可能會讓那些習慣于 自動提交事務模式的開發(fā)人員感到迷惑)。永遠使用清晰的事務聲明,即使只讀操作也是如此。進行顯式的事務聲明并不總是需要的,這取決于你的事務隔離級別和數(shù)據(jù)庫的能力,但不管怎么說,聲明事務總歸有益無害。當然,一個單獨的數(shù)據(jù)庫事務總是比很多瑣碎的事務性能更好,即時對讀數(shù)據(jù)而言也是一樣。

一個Hibernate應用程序可以運行在非托管環(huán)境中(也就是獨立運行的應用程序,簡單Web應用程序, 或者Swing圖形桌面應用程序),也可以運行在托管的J2EE環(huán)境中。在一個非托管環(huán)境中,Hibernate 通常自己負責管理數(shù)據(jù)庫連接池。應用程序開發(fā)人員必須手工設置事務聲明,換句話說,就是手工啟 動,提交,或者回滾數(shù)據(jù)庫事務。一個托管的環(huán)境通常提供了容器管理事務(CMT),例如事務裝配通過可聲 明的方式定義在EJB session beans的部署描述符中。可編程式事務聲明不再需要,即使是 Session 的同步也可以自動完成。

讓持久層具備可移植性是人們的理想,這種移植發(fā)生在非托管的本地資源環(huán)境,與依賴JTA但是使用BMT而非CMT的系統(tǒng)之間。在兩種情況下你都可以使用編程式的事務管理。Hibernate提供了一套稱為Transaction的封裝API, 用來把你的部署環(huán)境中的本地事務管理系統(tǒng)轉換到Hibernate事務上。這個API是可選的,但是我們強烈 推薦你使用,除非你用CMT session bean。

通常情況下,結束 Session 包含了四個不同的階段:

◆同步session(flush,刷出到磁盤)

◆提交事務

◆關閉session

◆處理異常

session的同步(flush,刷出)前面已經討論過了,我們現(xiàn)在進一步考察在托管和非托管環(huán)境下的事務聲明和異常處理。

1.非托管環(huán)境

如果Hibernat持久層運行在一個非托管環(huán)境中,數(shù)據(jù)庫連接通常由Hibernate的簡單(即非DataSource)連接池機制 來處理。session/transaction處理方式如下所示:

  1. //Non-managed environment idiom  
  2. Session sess = factory.openSession();  
  3. Transaction tx = null;  
  4. try {  
  5.     tx = sess.beginTransaction();  
  6.  
  7.     // do some work  
  8.     ...  
  9.  
  10.     tx.commit();  
  11. }  
  12. catch (RuntimeException e) {  
  13.     if (tx != null) tx.rollback();  
  14.     throw e; // or display error message  
  15. }  
  16. finally {  
  17.     sess.close();  
  18. }  

你不需要顯式flush() Session - 對commit()的調用會自動觸發(fā)session的同步(取決于session的第 10.10 節(jié) “Session刷出(flush)”)。調用 close() 標志session的結束。close()方法重要的暗示是,session釋放了JDBC連接。這段Java代碼在非托管環(huán)境下和JTA環(huán)境下都可以運行。

更加靈活的方案是Hibernate內置的"current session"上下文管理,前文已經講過:

  1. // Non-managed environment idiom with getCurrentSession()  
  2. try {  
  3.     factory.getCurrentSession().beginTransaction();  
  4.  
  5.     // do some work  
  6.     ...  
  7.  
  8.     factory.getCurrentSession().getTransaction().commit();  
  9. }  
  10. catch (RuntimeException e) {  
  11.     factory.getCurrentSession().getTransaction().rollback();  
  12.     throw e; // or display error message  
  13. }  

你很可能從未在一個通常的應用程序的業(yè)務代碼中見過這樣的代碼片斷:致命的(系統(tǒng))異常應該總是 在應用程序“頂層”被捕獲。換句話說,執(zhí)行Hibernate調用的代碼(在持久層)和處理 RuntimeException異常的代碼(通常只能清理和退出應用程序)應該在不同 的應用程序邏輯層。Hibernate的當前上下文管理可以極大地簡化這一設計,你所有的一切就是SessionFactory。 異常處理將在本章稍后進行討論。

請注意,你應該選擇 org.hibernate.transaction.JDBCTransactionFactory (這是默認選項),對第二個例子來說,hibernate.current_session_context_class應該是"thread"

2. 使用JTA

如果你的持久層運行在一個應用服務器中(例如,在EJB session beans的后面),Hibernate獲取 的每個數(shù)據(jù)源連接將自動成為全局JTA事務的一部分。 你可以安裝一個獨立的JTA實現(xiàn),使用它而不使用EJB。Hibernate提供了兩種策略進行JTA集成。

如果你使用bean管理事務(BMT),可以通過使用Hibernate的 Transaction API來告訴 應用服務器啟動和結束BMT事務。因此,事務管理代碼和在非托管環(huán)境下是一樣的。

  1. // BMT idiom  
  2. Session sess = factory.openSession();  
  3. Transaction tx = null;  
  4. try {  
  5.     tx = sess.beginTransaction();  
  6.  
  7.     // do some work  
  8.     ...  
  9.  
  10.     tx.commit();  
  11. }  
  12. catch (RuntimeException e) {  
  13.     if (tx != null) tx.rollback();  
  14.     throw e; // or display error message  
  15. }  
  16. finally {  
  17.     sess.close();  
  18. }  

如果你希望使用與事務綁定的Session,也就是使用getCurrentSession()來簡化上下文管理,你將不得不直接使用JTA UserTransactionAPI。

  1. // BMT idiom with getCurrentSession()  
  2. try {  
  3.     UserTransaction tx = (UserTransaction)new InitialContext()  
  4.                             .lookup("java:comp/UserTransaction");  
  5.  
  6.     tx.begin();  
  7.  
  8.     // Do some work on Session bound to transaction  
  9.     factory.getCurrentSession().load(...);  
  10.     factory.getCurrentSession().persist(...);  
  11.  
  12.     tx.commit();  
  13. }  
  14. catch (RuntimeException e) {  
  15.     tx.rollback();  
  16.     throw e; // or display error message  
  17. }  

在CMT方式下,事務聲明是在session bean的部署描述符中,而不需要編程。 因此,代碼被簡化為:

  1. // CMT idiom  
  2. Session sess = factory.getCurrentSession();  
  3.  
  4. // do some work  
  5. ...  

在CMT/EJB中甚至會自動rollback,因為假若有未捕獲的RuntimeException從session bean方法中拋出,這就會通知容器把全局事務回滾。這就意味著,在BMT或者CMT中,你根本就不需要使用Hibernate Transaction API ,你自動得到了綁定到事務的“當前”Session。

注意,當你配置Hibernate的transaction factory的時候,在直接使用JTA的時候(BMT),你應該選擇org.hibernate.transaction.JTATransactionFactory,在CMT session bean中選擇org.hibernate.transaction.CMTTransactionFactory。記得也要設置hibernate.transaction.manager_lookup_class。還有,確認你的hibernate.current_session_context_class未設置(為了向下兼容),或者設置為"jta"。

getCurrentSession()在JTA環(huán)境中有一個弊端。對after_statement連接釋放方式有一個警告,這是被默認使用的。因為JTA規(guī)范的一個很愚蠢的限制,Hibernate不可能自動清理任何未關閉的ScrollableResults 或者Iterator,它們是由scroll()或iterate()產生的。你must通過在finally塊中,顯式調用ScrollableResults.close()或者Hibernate.close(Iterator)方法來釋放底層數(shù)據(jù)庫游標。(當然,大部分程序完全可以很容易的避免在JTA或CMT代碼中出現(xiàn)scroll()或iterate()。)

3. 異常處理

如果 Session 拋出異常 (包括任何SQLException), 你應該立即回滾數(shù)據(jù)庫事務,調用 Session.close() ,丟棄該 Session實例。Session的某些方法可能會導致session 處于不一致的狀態(tài)。所有由Hibernate拋出的異常都視為不可以恢復的。確保在 finally 代碼塊中調用close()方法,以關閉掉 Session。

HibernateException是一個非檢查期異常(這不同于Hibernate老的版本), 它封裝了Hibernate持久層可能出現(xiàn)的大多數(shù)錯誤。我們的觀點是,不應該強迫應用程序開發(fā)人員 在底層捕獲無法恢復的異常。在大多數(shù)軟件系統(tǒng)中,非檢查期異常和致命異常都是在相應方法調用 的堆棧的頂層被處理的(也就是說,在軟件上面的邏輯層),并且提供一個錯誤信息給應用軟件的用戶 (或者采取其他某些相應的操作)。請注意,Hibernate也有可能拋出其他并不屬于 HibernateException的非檢查期異常。這些異常同樣也是無法恢復的,應該 采取某些相應的操作去處理。

在和數(shù)據(jù)庫進行交互時,Hibernate把捕獲的SQLException封裝為Hibernate的 JDBCException。事實上,Hibernate嘗試把異常轉換為更有實際含義 的JDBCException異常的子類。底層的SQLException可以 通過JDBCException.getCause()來得到。Hibernate通過使用關聯(lián)到 SessionFactory上的SQLExceptionConverter來 把SQLException轉換為一個對應的JDBCException 異常的子類。默認情況下,SQLExceptionConverter可以通過配置dialect 選項指定;此外,也可以使用用戶自定義的實現(xiàn)類(參考javadocs SQLExceptionConverterFactory類來了解詳情)。標準的 JDBCException子類型是:

◆JDBCConnectionException - 指明底層的JDBC通訊出現(xiàn)錯誤

◆SQLGrammarException - 指明發(fā)送的SQL語句的語法或者格式錯誤

◆ConstraintViolationException - 指明某種類型的約束違例錯誤

◆LockAcquisitionException - 指明了在執(zhí)行請求操作時,獲取 所需的鎖級別時出現(xiàn)的錯誤。

◆GenericJDBCException - 不屬于任何其他種類的原生異常

4. 事務超時

EJB這樣的托管環(huán)境有一項極為重要的特性,而它從未在非托管環(huán)境中提供過,那就是事務超時。在出現(xiàn)錯誤的事務行為的時候,超時可以確保不會無限掛起資源、對用戶沒有交代。在托管(JTA)環(huán)境之外,Hibernate無法完全提供這一功能。但是,Hiberante至少可以控制數(shù)據(jù)訪問,確保數(shù)據(jù)庫級別的死鎖,和返回巨大結果集的查詢被限定在一個規(guī)定的時間內。在托管環(huán)境中,Hibernate會把事務超時轉交給JTA。這一功能通過Hibernate Transaction對象進行抽象。

  1. Session sess = factory.openSession();  
  2. try {  
  3.     //set transaction timeout to 3 seconds  
  4.     sess.getTransaction().setTimeout(3);  
  5.     sess.getTransaction().begin();  
  6.  
  7.     // do some work  
  8.     ...  
  9.  
  10.     sess.getTransaction().commit()  
  11. }  
  12. catch (RuntimeException e) {  
  13.     sess.getTransaction().rollback();  
  14.     throw e; // or display error message  
  15. }  
  16. finally {  
  17.     sess.close();  
  18. }  

注意setTimeout()不應該在CMT bean中調用,此時事務超時值應該是被聲明式定義的。

【編輯推薦】

  1. 淺析Hibernate VO與PO區(qū)別
  2. Hibernate中merge()方法解析
  3. Hibernate中Criteria攻略詳解
  4. 簡述Hibernate部分查詢語言(一)
  5. 簡述Hibernate三種查詢的應用
責任編輯:仲衡 來源: diybl
相關推薦

2009-09-25 13:18:15

Hibernate數(shù)據(jù)

2009-07-02 09:35:02

hibernate訪問

2010-10-08 09:38:55

Android數(shù)據(jù)庫事

2009-06-24 07:53:47

Hibernate數(shù)據(jù)

2025-04-08 06:00:00

2009-06-02 14:36:28

HibernateMySQLEclipse

2009-09-28 13:33:48

Hibernate訪問

2009-06-24 07:58:52

Hibernate多數(shù)

2024-05-28 00:00:30

Golang數(shù)據(jù)庫

2020-06-17 16:56:36

數(shù)據(jù)庫MySQL跨行事務

2015-03-04 13:53:33

MySQL數(shù)據(jù)庫優(yōu)化SQL優(yōu)化

2017-08-22 17:10:45

數(shù)據(jù)庫MySQL事務模型

2009-09-28 13:29:41

加載過程Hibernate訪問

2010-05-31 15:12:44

MySQL數(shù)據(jù)庫

2018-09-06 14:53:39

數(shù)據(jù)庫事務隔離隔離級別

2024-11-14 11:07:15

2009-08-06 18:10:06

C#數(shù)據(jù)庫事務

2011-08-12 13:33:31

Oracle數(shù)據(jù)庫自治事務

2023-10-11 08:09:53

事務隔離級別

2018-07-20 11:10:21

數(shù)據(jù)庫事務隔離性
點贊
收藏

51CTO技術棧公眾號