事务是的特性之一是原子(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 可以不用介入程式之中,从物件的角度来看,并不知道它正被纳入事务管理之中, 在不需要事务管理的时候,只要在设定档案上修改一下设定,即可移去事务管理服务。