7. 事务


1. 事务是什么

事务就是一项通常包含若干步骤的工作单元,这些步骤必须作为整体来执行,无论成功还是失败。

  • 自动事务:针对那些简单的仅由一条语句构成的事务,这种事务不需要显示划定事务边界
  • 局部事务:指那种简单的范围较窄的事务,这种事务虽然涉及很多条语句,但只作用于一个数据库
  • 全局事务:复杂范围较广的事务,往往涉及许多语句和布置一个数据库
  • 定制事务:ibatis支持由用户提供的连接

事务的特性:
  • 原子性(atomicity)
  • 一致性(consistency)
  • 隔离性(isolation):隔离级别(读未提交数据、读已提交数据、可重复读、串行化)
  • 持久性(durability)

2. 自动事务

ibatis处理的只有事务,对“自动提交”的支持完全是间接的。


3. 局部事务

仅仅涉及一个应用程序,一种资源,并且一次只能处理一个事务。




局部事务在ibatis的SQLMap配置文件中被配置为一个JDBC类型的事务管理器:
<transactionManager type="JDBC">
<dataSource type="SIMPLE">
<property …/>
<property …/>
<property …/>
</dataSource>
</transactionManager>

public void runStatementsUsingLocalTransactions() {
SqlMapClient sqlMapClient =
SqlMapClientConfig.getSqlMapClient();
try {
sqlMapClient.startTransaction();
Person p =
(Person)sqlMapClient.queryForObject
("getPerson", new Integer(9));
p.setLastName("Smith");
sqlMapClient.update("updatePerson", p);
Department d =
(Department)sqlMapClient.queryForObject
("getDept", new Integer(3));
p.setDepartment(d);
sqlMapClient.update("updatePersonDept", p);
sqlMapClient.commitTransaction();
} finally {
sqlMapClient.endTransaction();
}
}


4. 全局事务





4.1 使用主动或被动事务

主动参与: ibatis会查找全局事务上下文,以某种恰当的方式管理它。
被动参与:ibatis忽略当前应用程序所有关于开始事务、提交事务、结束事务的指令代码。出现错误时,不是主动回滚而是抛出异常。ibatis假设抛出异常就可以引起事务回滚。
<transactionManager type="JTA"><span style="white-space:pre">									</span>//主动参与
	<property name="UserTransaction" value="java:/ctx/con/someUserTransaction" />
	<dataSource type="JNDI">
		<property name="DataSource" value="java:comp/env/jdbc/someDataSource" />
	</dataSource>
</transactionManager>

<transactionManager type="EXTERNAL"><span style="white-space:pre">								</span>//被动参与
	<dataSource type="JNDI">
		<property name="DataSource" value="java:comp/env/jdbc/someDataSource" />
	</dataSource>
</transactionManager>

4.2 开始、提交以及结束事务

与局部事务一样


5 定制事务

方法一:使用ibatis某些接口,自己写一个事务管理器,然后把它插入到SQL Map配置文件(12章)
方法二:向ibatis传递一个要使用JDBC  Connection实例,从而允许你拥有对连接和事务管理的完全控制权

向ibatis的SqlMapClient实例传递一个Connection实例的方法有两种:
第一种使用SqlMapClient类的setUserConnection(Connection)方法

	public void runStatementsUsingSetUserConnection() {
		SqlMapClient sqlMapClient = SqlMapClientConfig.getSqlMapClient();
		Connection conn = null;
		try {
			conn = dataSource.getConnection();
			conn.setAutoCommit(false);<span style="white-space:pre">							</span>//////
			sqlMapClient.setUserConnection(conn);<span style="white-space:pre">						</span>///
			Person p = (Person) sqlMapClient.queryForObject("getPerson", new Integer(9));
			p.setLastName("Smith");
			sqlMapClient.update("updatePerson", p);
			Department d = (Department) sqlMapClient.queryForObject("getDept", new Integer(3));
			p.setDepartment(d);
			sqlMapClient.update("updatePersonDept", p);
			conn.commit();<span style="white-space:pre">									</span>///
		} finally {
			sqlMapClient.setUserConnection(null);<span style="white-space:pre">						</span>///
			if (conn != null)
				conn.close();<span style="white-space:pre">								</span>///
		}
	}



第二种使用sqlMapClient类的openSession(Connection)方法。(推荐使用)

public void runStatementsUsingSetUserConnection() {
		SqlMapClient sqlMapClient = SqlMapClientConfig.getSqlMapClient();
		Connection conn = null;<span style="white-space:pre">							</span>//////
		SqlMapSession session = null;<span style="white-space:pre">						</span>//////
		try {
			conn = dataSource.getConnection();
			conn.setAutoCommit(false);<span style="white-space:pre">					</span>//////
			session = sqlMapClient.openSession(conn);<span style="white-space:pre">			</span>///
			Person p = (Person) session.queryForObject("getPerson", new Integer(9));
			p.setLastName("Smith");
			session.update("updatePerson", p);
			Department d = (Department) session.queryForObject("getDept", new Integer(3));
			p.setDepartment(d);
			session.update("updatePersonDept", p);

			conn.commit();<span style="white-space:pre">							</span>///
		} finally {
			if (session != null)
				session.close();<span style="white-space:pre">					</span>///
			if (conn != null)<span style="white-space:pre">	</span>
				conn.close();<span style="white-space:pre">						</span>///
		}
	}

仍然需要定义一个EXTERNAL类型的事务管理器,至少提供一个SIMPLE类型的DataSource,否则,向延迟加载这样的特征就无法正常工作。

6. 事务划界


事务的范围越宽越好,但绝不能超过一次用户动作的范围。


将事务在业务逻辑层划界



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值