ibatis 事務管理


事務管理


基於JDBC 的事務管理機制
ibatis 提供了自動化的JDBC 事務管理機制。
對於傳統JDBC Connection 而言,我們獲取Connection 實例之后,需要調用Connection.setAutoCommit 設定事務提交模式。在AutoCommit 為true 的情況下,JDBC 會對我們的操作進行自動提交,此時,每個JDBC 操作都是一個獨立的任務。為了實現整體事務的原子性,我們需要將AutoCommit 設為false ,並結合Connection.commit/rollback 方法進行事務的提交/回滾操作。


ibatis 的所謂“自動化的事務提交機制”,即ibatis 會根據當前的調用環境,自動判斷操作是否需要自動提交。
如果代碼沒有顯式的調用SqlMapClient.startTransaction() 方法,則ibatis會將當前的數據庫操作視為自動提交模式(AutoCommit=true),如:
sqlMap = xmlBuilder.buildSqlMap(reader); 
User user = new User(); 
user.setId(new Integer(1)); 
user.setName("Erica"); 
user.setSex(new Integer(0)); 
sqlMap.update("User.updateUser", user); 
User user2 = new User(); 
user2.setId(new Integer(2)); 
user2.setName("Kevin"); 
user2.setSex(new Integer(1)); 
sqlMap.update("User.updateUser", user2); 
在執行的時候,會自動判定運行環境,這里操作sqlMap.update ibatis 當前的update並沒有相對應的事務范圍(startTransaction 和endTransaction 代碼塊),於是ibatis 將其作為一個單獨的事務,並自動提交。對於上面的代碼,update 執行了兩次,與其相對應,事務也提交了兩次(即每個update 操作為一個單獨的事務)。不過,值得注意的是,這里的所謂“自動判定”,可能有些誤導,ibatis 並沒有去檢查當前是否已經有事務開啟,從而判斷當前數據庫連接是否設定為自動提交。實際上,在執行update 語句時,sqlMap 會檢查當前的Session 是否已經關聯了某個數據庫連接,如果沒有,則取一個數據庫連接,將其AutoCommit 屬性設為true ,然后執行update 操作,執行完之后又將這個連接釋放。這樣,上面兩次update 操作實際上先后獲取了兩個數據庫連接,而不是我們通常所認為的兩次update 操作都基於同一個JDBC Connection 。這點在開發時需特別注意。


對於多條SQL 組合而成的一個JDBC 事務操作而言,必須使用
startTransaction、commit 和endTransaction 操作以實現整體事務的原子性。

如:
try{ 
sqlMap = xmlBuilder.buildSqlMap(reader); 
sqlMap.startTransaction(); 
User user = new User(); 
user.setId(new Integer(1)); 
user.setName("Erica"); 
user.setSex(new Integer(0)); 
sqlMap.update("User.updateUser", user); 
User user2 = new User(); 
user2.setId(new Integer(2)); 
user2.setName("Kevin"); 
user2.setSex(new Integer(1)); 
sqlMap.update("User.updateUser", user2); 
sqlMap.commitTransaction(); 
}finally{ 
sqlMap.endTransaction(); 

如果user1 或者user2 的update 操作失敗,整個事務就會在endTransaction 時回滾,從而保證了兩次update 操作的原子性。


基於JTA 的事務管理機制
JTA 提供了跨數據庫連接(或其他JTA 資源)的事務管理能力。這一點是與JDBC Transaction 最大的差異。
JDBC 事務由Connnection 管理,也就是說,事務管理實際上是在JDBC Connection 中實現。事務周期限於Connection 的生命周期。同樣,對於基於JDBC 的ibatis 事務管理機制而言,事務管理在SqlMapClient 所依托的JDBC Connection 中實現,事務周期限於SqlMapClient 的生命周期。
JTA 事務管理則由JTA 容器實現,JTA 容器對當前加入事務的眾多Connection 進行調度,實現其事務性要求。JTA 的事務周期可橫跨多個JDBC Connection 生命周期。


同樣,對於基於JTA 事務的ibatis 而言,JTA 事務橫跨可橫跨多個SqlMapClient 。
下面這幅圖形象的說明了這個問題:

為了在ibatis 中使用JTA 事務管理,我們需要在配置文件中加以設定: 
<transactionManager type="JTA"> 
……
</transactionManager>
在實際開發中,我們可能需要面對分布式事務的處理,如系統范圍內包含了多個數據庫, 
也許還引入了JMS 上的事務管理(這在EAI 系統實現中非常常見)。我們就需要引入JTA 
以實現系統范圍內的全局事務,如下面示例中,我們同時將user 對象更新到兩個不同的數
據庫: 
User user = new User(); 
user.setId(new Integer(1)); 
user.setName("Erica"); 
user.setSex(new Integer(0)); 
sqlMap1 = xmlBuilder.buildSqlMap(db1Config); 
sqlMap2 = xmlBuilder.buildSqlMap(db2Config); 
try{ 
sqlMap1.startTransaction(); 
sqlMap1.update("User.updateUser", user); 
sqlMap2.update("User.updateUser", user); 
sqlMap1. commitTransaction();
}finally{ 
sqlMap1.endTransaction(); 

上面的代碼中,兩個針對不同數據庫的實例,在同一個事務中SqlMapClient JTA 
對user 對象所對應的數據庫記錄進行更新。外層的sqlMap1 啟動了一個全局事務,此
事務將涵蓋本線程內commitTransaction 之前的所有數據庫操作。只要其間發生了

異常,則整個事務都將被回滾。
外部事務管理
基於JTA 的事務管理還有另外一個特殊情況,就是利用外部事務管理機制。
對於外部事務管理,我們需要在配置文件中進行如下設定: 
<transactionManager type="EXTERNAL"> 
……
</transactionManager>
下面是一個外部事務管理的典型示例: 
UserTransaction tx = new InitialContext().lookup(“……”); 
……
sqlMap1 = xmlBuilder.buildSqlMap(db1Config); 
sqlMap2 = xmlBuilder.buildSqlMap(db2Config); 
sqlMap1.update("User.updateUser", user); 
sqlMap2.update("User.updateUser", user); 
……
tx.commit(); 
此時,我們借助實例啟動了一個全局事務。之后的操作JTA UserTransaction ibatis 
( sqlMap1.update 和sqlMap2.update)全部被包含在此全局事務之中,當
UserTransaction 提交的時候,
ibatis 操作被包含在事務中提交,反之,如果UserTransaction 
回滾,那么其間的ibatis 操作也將作為事務的一部分被回滾。這樣,我們就實現了ibatis 
外部的事務控制。
另一種外部事務管理方式是借助EJB 容器,通過EJB 的部署配置,我們可以指定
EJB 方法的事務性
下面是一個Session Bean 的doUpdate 方法,它的事務屬性被申明為“Required”, 
EJB 容器將自動維護此方法執行過程中的事務: 
/**

@ejb.interface-method

view-type="remote"
*

@ejb.transaction type = "Required"
**/
public void doUpdate(){
//EJB環境中,通過部署配置即可實現事務申明,而無需顯式調用事務
……
sqlMap1 = xmlBuilder.buildSqlMap(db1Config); 
sqlMap2 = xmlBuilder.buildSqlMap(db2Config); 
sqlMap1.update("User.updateUser", user); 
sqlMap2.update("User.updateUser", user); 
……
}//方法結束時,如果沒有異常發生,則事務由EJB容器自動提交。
上面的示例中,ibatis 數據操作的事務管理將全部委托給EJB 容器管理,由EJB 
容器控制其事務調度。

在上面JTA 事務管理的例子中,為了保持清晰,我們省略了startTransaction 、
commitTransaction 和endTransaction 的編寫,在這種情況下,調用ibatis 
的事務管理方法並非必須,不過在實際開發時,請酌情添加startTransaction 、
commitTransaction 和endTransaction 語句,這樣可以獲得更好的性能(如果
省略了startTransaction 、commitTransaction 和endTransaction 語句, 
ibatis 將為每個數據操作獲取一個數據連接,就算引入了數據庫連接池機制,這樣的
無謂開銷也應盡量避免,具體請參見JDBC 事務管理中的描述),並保持代碼風格的統
一。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM