Spring框架提供了两种程序化事物管理
- 使用
TransactionTemplate
- 直接使用
PlatformTransactionManager
实现类
一般推荐使用TransactionTemplate
进行程序化事物管理。第二种方式与使用JTA UserTransaction
API 相似,虽然少了一些异常处理。
11.6.1 使用TransactionTemplate
TransactionTemplate
采用了Spring模板中与JdbcTemplate相同的方式。使用一种回调函数,去掉了必须的做的应用程序代码并释放了事务性资源文件,产生的是目的驱动的代码,那些代码就是程序开发者需要做的。
注意:如同你在下面的例子看到的,使用TransactionTemplate
完全耦合了Spring框架的事物底层和APIs。编程式开发是否适合你的开发需求取决于你自己的。
必须在一个事物上下文中运行的并且直接使用TransactionTemplate
应用程序代码,如下所示。你,作为一个程序开发者,写一个TransactionCallback
实现类(通常是一个注解匿名类),其包含了在一个事物上下文中要执行的代码。稍后传递TransactionCallback
的实例给execute
(...)方法,其是
TransactionTemplate类暴露的方法。
public class SimpleService implements Service {
// single TransactionTemplate shared amongst all methods in this instance
private final TransactionTemplate transactionTemplate;
// use constructor-injection to supply the PlatformTransactionManager
public SimpleService(PlatformTransactionManager transactionManager) {
Assert.notNull(transactionManager, "The transactionManager argument must not be null.");
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
public Object someServiceMethod() {
return transactionTemplate.execute(new TransactionCallback() {
// the code in this method executes in a transactional context
public Object doInTransaction(TransactionStatus status) {
updateOperation1();
return resultOfUpdateOperation2();
}
});
}
}
如果没有返回值,使用方便的TransactionCallbackWithoutResult
类(带有一个匿名类),如下:
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
updateOperation1();
updateOperation2();
}
});
回滚的代码可以通过
TransactionStatus
对象调用setRollbackOnly()
方法回滚事物。
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
updateOperation1();
updateOperation2();
} catch (SomeBusinessExeption ex) {
status.setRollbackOnly();
}
}
});
指定事物设置
你可以指定事物设置,比如TransactionTemplate
的传播性模式,隔离级别,超时等等,不管是编程式或者声明式。TransactionTemplate
实例一般地有默认事物设置。下面的例子显示了一个特定的TransactionTemplate的事物设置的编程定制。
public class SimpleService implements Service {
private final TransactionTemplate transactionTemplate;
public SimpleService(PlatformTransactionManager transactionManager) {
Assert.notNull(transactionManager, "The transactionManager argument must not be null.");
this.transactionTemplate = new TransactionTemplate(transactionManager);
// the transaction settings can be set here explicitly if so desired
this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
this.transactionTemplate.setTimeout(30); // 30 seconds
// and so forth...
}
}
下面的例子定义了
TransactionTemplate
的通用事物设置,使用了Spring XML配置。sharedTransactionTemplate
可以按需注入到许多业务中。
<bean id="sharedTransactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/>
<property name="timeout" value="30"/>
</bean>"
最后,
TransactionTemplate
类的实例时线程安全的,在那个实例中不包含任何会话状态。
TransactionTemplate
实例却是包含了配置状态,这样大量的类可能共享单一的
TransactionTemplate
实例,如果一个类需要用不同设置的
TransactionTemplate
(例如,不同的隔离级别),那么那么需要创建两个独特的
TransactionTemplate
实例。
11.6.2 使用PlatformTransactionManager
也可以直接使用
org.springframework.transaction.PlatformTransactionManager
管理你的事物。简单的传递PlatformTransactionManager
的实例给一个bean的引用。之后,使用TransactionDefinition
和TransactionStatus
对象可以初始化事物,回滚和提交。
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can only be done programmatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
// execute your business logic here
}
catch (MyException ex) {
txManager.rollback(status);
throw ex;
}
txManager.commit(status);