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事务

您可以选择外部管理或手工编程管理全局事务,或实现一个像EJB一样的架构。使用EJB,您可以通过使用EJB的描述文件定义事务范围。要支持外部管理或手工编程管理全局事务,必须在SQL Map配置文件中设定<transactionManager>的type属性为EXTERNAL。使用外部管理的全局事务,SQL Map事务控制方法变得有的多余,因为事务的开始、提交和回退都由外部的事务管理器来控制。但是使用SqlMapClient的startTransaction(),commitTransaction()和rollbackTransaction()来划分事务范围(相对于自动的事务处理),还是对提高性能有帮助。继续使用这些方法,可以保持编程规范的一致性。另一个好处是,在某些情况下,您可能需要改变关闭资源的顺序(不幸的是,不同的应用服务器和事务管理器具有不同的规则)。除了这些考虑,要使用全局事务,不需要改变您的SQL Map代码。

  • 受管理的(Managed)全局事务

SQL Map框架也可以为您管理全局事务。要支持受管理的全局事务,必须在SQL Map配置文件中设定<transactionManager>的type属性为JTA,并设定“UserTransaction”属性为JNDI的全名,以使SqlMapClient实例能找到UserTransaction对象。
使用全局事务编程,代码没有多大的不同,但有几个小小的地方要注意。例如:
try {
orderSqlMap.startTransaction();
storeSqlMap.startTransaction();
orderSqlMap.insertOrder(...);
orderSqlMap.updateQuantity(...);
storeSqlMap.commitTransaction();
orderSqlMap.commitTransaction();
} finally {
try {
storeSqlMap.endTransaction();
} finally {
orderSqlMap.endTransaction();
}
}
上面的例子中,假设我们通过两个SqlMapClient来使用两个不同的数据库。第一个开始事务的SqlMapClient(orderSqlMap)同时也开始了一个全局事务。在这之后,所有其他的操作将被看做是这个全局事务的一部分,直到同一个SqlMapClient(orderSqlMap)调用commitTransaction()或rollbackTransaction(),届时全局事务被提交并完成其他所有的操作。
警告!虽然这些看起来很简单,但记住不要滥用全局(分布式)事务,这点很重要。这样做既有性能方面的考虑,同时也是因为全局(分布式)事务,这点很重要。这样做既有性能方面的考虑,同时也是因为全局事务会让应用服务器和数据库驱动程序的设置变得更复杂。虽然看起来简单,您可能还是会遇到一些困难。记住,EJB拥有更多厂商和工具支持。对于需要分布式事务的应用,最好还是使用Session EJB。

批处理

如果要执行很多非查询(insert/update/delete)的语句,您可能喜欢讲他们作为一个批处理来执行,以减少网络通讯流量,并让JDBC Driver进行优化(例如压缩)。SQL Map API使用批处理很简单,可以使用两个简单的方法划分批处理的边界:
sqlMap.startBatch();
// ...execute statements in between
sqlMap.executeBatch();
当调用endBatch()方法时,所有的批处理语句将通过JDBC Driver来执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值