配置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规范的资源),即同时成功或失败。