ITEEDU

Spring  对事务的支援

事务是的特性之一是原子(Atomic)操作的工作单元,以资料库存取的实例来说,就是一组 SQL 指令,这一组 SQL 指令必须全部执行成功,若因为某个原因(例如其中一行 SQL 有错误),则先 前所有执行过的 SQL 指令撤消。

举个简单的例子,一个客户从 A 银行转帐至 B 银行,要作的动作为从 A 银行的帐户扣款、在 B 银行的帐户加上转帐的金额,两个动作必须成功,如果有一个动作失败,则此次转帐失败。

在 JDBC 中,可以操作 Connection 的 setAutoCommit()方法,给定它 false 引数,在下达一连串 的 SQL 语句后,自行呼叫 Connection 的 commit()来送出变更,如果中间发生错误,则呼叫 rollback()来撤消所有的执行,例如:

try {
	..... 
	connection.setAutoCommit(false);
	.....
	// 一连串 SQL 操作
	connection.commit();
} catch(SQLException) {
	// 发生错误,撤消所有变更
	connection.rollback();
}

在 Spring 中对 JDBC 的事务管理加以封装,Spring 事务管理的抽象其关键在于 org.springframework.transaction.PlatformTransactionManager 介面的实现:

...
public interface PlatformTransactionManager { 
	TransactionStatus getTransaction(TransactionDefinition definition)
					throws TransactionException;
	void commit(TransactionStatus status)
					throws TransactionException;
	void rollback(TransactionStatus status)
					throws TransactionException;
}

PlatformTransactionManager 介面有许多具体的事务实现类别,例如 DataSourceTransactionManager、 HibernateTransactionManager、JdoTransactionManager、 JtaTransactionManager 等,藉由依赖于 PlatformTransactionManager 介面及各种的技术实现, Spring 在事务管理上可以让开发人员使用一致的编程模 型,即使使用的是不同的事务管理技术。

TransactionException 是 Unchecked Exception 的。 事务的失败通常都是致命的错误,Spring 不强迫您一定要处理,而让您自行选择是否要捕捉例外。

getTransaction()方法根据一个 TransactionDefinition 物件来返回一个 TransactionStatus 物件, TransactionDefinition 介面的实例定义了事务的隔离程度(Isolation level)、传播 行为(Propagation behavior)、超时(Timeout)、唯读(Read-only)等,TransactionStatus 代表着一个新的事务发起或已经存在的交 易,您可以藉由它控制事务的执行或调查事务的状态:

...
public interface TransactionStatus {
	boolean isNewTransaction(); 
	void setRollbackOnly(); 
	boolean isRollbackOnly();
}

Spring 提供编程式的事务管理(Programmatic transaction management)与宣告式的事务管理 (Declarative transaction management):

•      编程式的事务管理

编程式的事务管理让您可以清楚的控制事务的边界,也就是让您自行实现事务何时开始、撤消操 作的时机、事务何时结束等,可以实现细粒度的事务控制。

•      宣告式的事务管理

然而多数的情况下,事务并不需要细粒度的控制,采用宣告式的事务管理,好处是 Spring 事务 管理的相关 API 可以不用介入程式之中,从物件的角度来看,并不知道它正被纳入事务管理之中, 在不需要事务管理的时候,只要在设定档案上修改一下设定,即可移去事务管理服务。