問題1:到底該用getTransaction還是beginTransaction? 上圖說明的問題: 第1步,調用session.getTransaction()的時候,會創建一個全新的Transaction對象; 第2步,調用session.beginTransaction()的時候,會創建一個全 ...
問題1:到底該用getTransaction還是beginTransaction?
上圖說明的問題:
- 第1步,調用session.getTransaction()的時候,會創建一個全新的Transaction對象;
- 第2步,調用session.beginTransaction()的時候,會創建一個全新的Transaction對象,沒有使用上一步的Transaction對象哦;
- 第3步,再次調用session.getTransaction()的時候,會看到這時返回的是第2步創建的Transaction對象;
- 第4步,這時調用session.getCurrentTransaction(),會看到仍然返回第2步創建的Transaction對象;
結論:通常情況下一個session內只會處理一個事務,所以大多數時候可直接調用session.beginTransaction()方法創建一個全新的transaction對象,並開始該事務。
問題2:getCurrentTransaction跟getTransaction有什麼區別?
上圖說明的問題:
- 第1步,直接調用session.getCurrentTransaction()會返回null;
- 第2步,調用session.beginTransaction() 會創建一個全新的Transaction對象;
- 第3步和第4步說明,當session.beginTransaction()被調用後,不管使用session.getTransaction()還是session.getCurrentTransaction()都是返回beginTransaction時創建的同一個Transaction對象。
結論:當session.beginTransaction被調用之後,不管是用session.getTransaction還是getCurrentTransaction返回的都是同一個transaction對象;如果沒有開始事務,getTransaction會創建一個新的transaction對象,getCurrentTransaction會返回null。
問題3:如果不斷的調用getTransaction,是否會返回同一個transaction對象?
結論:上圖說明,每次調用session.getTransaction()都會創建全新的Transaction對象,如果是這樣,那這個方法如果叫session.createTransaction()或許更加合理,但是呢,如果session已經有begin了的transaction,該方法又不會創建新的transaction。所以說,這個命名真的是一個巨大的坑,在程式中應該避免使用這個方法,否則難以理解是否是同一個Transaction對象;
問題4: 通過getTransaction創建的transaction對象begin之後,再次調用session.beginTransaction是否會開啟兩個事務?
結論:上圖說明,session.getTransaction().begin() 與 session.beginTransaction() 是完全一模一樣的。一個session同時只能有一個transaction是active的(開啟狀態)。
那麼,既然一個session可以通過session.getTransaction()創建無數個Transaction實例,那麼這些Transaction實例是否可以獨立工作呢?但是下方的最後一行代碼就報錯了:
Transaction transaction1 = db.getSession().getTransaction(); Transaction transaction2 = db.getSession().getTransaction(); transaction1.begin(); transaction2.begin();
原因就是一個session不能同時開啟多個transaction。
問題5:當transaction.commit()調用之後再次調用session.beginTransaction是否會繼續沿用之前的transaction?
上圖說明的問題:
- 一個session裡面是可以開啟多個transaction的,但是一個transaction的begin方法只有在其他transaction都不是active的時候才可以調用成功,也就是說一個session同時僅允許一個active的transaction;
- 當一個transaction.commit() 方法調用之後,再次調用session.getTransaction()就會創建一個全新的Transaction對象,這一點非常重要,千萬不要以為同一個session在調用transaction.begin()之後再調用session.getTransaction()都只會返回同一個Transaction對象,如果之前begin的那個transaction已經commit,這時再調用session.getTransaction()就是全新的transaction對象了。
問題6:是否總是需要手工調用transaction.rollback實現事務回滾?
問題:假如一個transaction.commit()方法提交了2條sql,但是第2條由於數據驗證錯誤而拋了異常,那麼請問,如果不手工調用transaction.rollback()方法,該transaction的第1條sql是否會執行成功。
答案:不會執行成功。這個結論告訴我們,如果之前沒有調用session.flush()而是最後一起執行transaction.commit(),那麼不需要加try-catch來手工調用transaction.rollback()
本文中的測試來自jframe 框架
基於spring mvc搭建的多層級多模塊java web應用程式框架。包含:基礎設施層、資料庫定義規範、資料庫訪問規範、日誌記錄規範、多層級異常捕獲、標準ajax規範、母版頁規範、視圖呈現規範、JavaScript框架規範等。實際上該框架定義的規範極其詳細,比如資料庫定義層:枚舉類使用規範、datetime/bool/string欄位規範、1對1、1對多、多對1、多對多外鍵關係映射規範、父類定義規範、欄位註釋規範、懶載入規範等等。。。
技術交流QQ群:651499479,歡迎java大神指點迷津,也歡迎新手進群學習。
github地址: https://github.com/leotsai/jframe
THE END.