iBATIS SQL Maps之配置SQL Map、事務處理和批處理。
配置SQL Map
一旦您建立了SQL Map XML定義檔案和SQL Map配置檔案,配置SQL Map就是一件極其簡單的事情。Sql Map使用XmlSqlMapClientBuilder來建立。這個類有一個靜態方法叫buildSqlMap。方法buildSqlMap簡單地用一個Reader物件為引數,讀入sqlMap-config.xml檔案(不必是這個檔名)的內容。
String resource = "com/ibatis/example/sqlMap-config.xml";
Reader reader = Resource.getResourceAsReader(resource);
SqlMapClientsqlMap = SqlMapClientBuilder.buildSqlMap(reader);
事務處理
預設情況下,呼叫SqlMapClient物件的任意executeXxxx()方法將預設地自動COMMIT/ROLLBACK。這意味著每次呼叫executeXxxx()方法都是一個獨立的事務。這確實很簡單,但對於需要在同一個事務中執行多個語句的情況(即只能同時成功或失敗),並不適用。這正是事務處理要關心的事情。
如果您在使用Global Transaction(在SQL Map配置檔案中設定),您可以使用自動提交併且可以得到在同一事務中執行的效果。但為了提高效能,最好是明確地劃分事務的範圍,因為這樣做可以減少連線池的通訊流量和資料庫連線的初始化。
SqlMapClient物件擁有讓您定義事務範圍的方法。使用下面SqlMapClient類的方法,可以開始、提交和/或回退事務:
public void startTransaction() throws SQLException;
public void commitTransaction() throws SQLException;
public void endTransaction() throws SQLException;
開始一個事務,意味著您從連線池中得到一個連線,開啟它並執行查詢和更新SQL操作。使用事務處理的例子如下:
private Reader reader = new Resources.getResourceAsReader("com/ibatis/example/sqlMap-config.xml");
private SqlMapClientsqlMap = XxmlSqlMapBuilder.buildSqlMap(reader);
public updateItemDescription(String itemId, String newDescription) throws SQLException {
try{
sqlMap.startTransaction();
Item item = (Item) sqlMap.queryForObject("getItem" , itemId);
item.setDescription(newDescription);
sqlMap.update("updateItem" , item);
sqlMap.commitTransaction();
} finally {
sqlMap.endTransaction();
}
}
注意!事務不能巢狀。在呼叫commit()或rollback()之前,從同一執行緒多次呼叫.startTransaction,將引起丟擲例外。換句話說,對於每個SqlMap例項,每個執行緒最多隻能開啟一個事務。
注意!SqlMapClient事務處理使用Java的ThreadLocal儲存事務物件。這意味著在處理事務時,每個呼叫startTransaction()的執行緒,將得到一個唯一的Connection物件。將一個Connection物件返回資料來源(或關閉連線)唯一的方法是呼叫commitTransaction()或rollbackTransaction()方法。否則,會用光連線池中的連線並導致死鎖。
自動的事務處理
雖然極力推薦使用明確劃分的事務範圍,在簡單需求(通常是隻讀)的情況下,可以使用簡化的語法。如果您沒有使用startTransaction(),commitTransaction()和rollbackTransaction()方法來明確地劃分事務範圍,事務將會自動執行。例如:
private Reader reader = new Resources.getResourceAsReader("com/ibatis/example/sqlMap-config.xml");
private SqlMapClientsqlMap = XxmlSqlMapBuilder.buildSqlMap(reader);
public updateItemDescription(String itemId, String newDescription) throws SQLException {
try{
Item item = (Item) sqlMap.queryForObject("getItem" , itemId);
item.setDescription("TX1");
// No transaction demarcated, so transaction will be automatic(implied)
sqlMap.update("updateItem" , item);
item.setDescription(newDescription);
item.setDescription("TX2");
// No transaction demarcated, so transaction will be automatic(implied)
sqlMap.update("updateItem" , item);
} catch(SQLException e){
throw (SQLException)e.filllnStackTrance();
}
}
注意!使用自動事務處理要非常小心。雖然看起來很有吸引力,但如果有多個數據更新操作要在同一事務中處理時,您會遇到麻煩。在上面的例子中,如果第二個“updateItem”操作失敗,第一個“updateItem”操作仍然會執行,description會更新成“TX1”。
全域性(分散式)事務
SQL Map框架支援全域性事務。全域性事務也叫分散式事務,他可以允許您在同一事務中更新多個數據庫(或其他符合JTA規範的資源),即同時成功或失敗。
- External/Programmatic Global事務
- 受管理的(Managed)全域性事務