虽然Spring框架推荐使用声明式事务管理,但是我们也要了解一下Spring的编程式事务。
Spring编程式事务仅适用于操作简单的事务,有两种编程实现的方式:
- 直接使用org.springframework.transaction.PlatformTransactionManager接口的某个实现类
类似于直接使用JTA的事务API
- 使用org.springframework.transaction.support.TransactionTemplate类(推荐方式)
TransactionTemplate类是org.springframework.transaction.TransactionDefinition接口的实现。
TransactionTemplate是线程安全的,即其不维持事务运行的状态。但是TransactionTemplate维持着配置参数,可以作用于不同的事务中。
1.使用org.springframework.transaction.support.TransactionTemplate类实现Spring的编程式事务
1) 基本的代码如下所示:
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) {
try {
updateOperation1();
return resultOfUpdateOperation2();
} catch (SomeBusinessExeption ex) {
status.setRollbackOnly();
}
}
});
}
}
说明:
初始化TransactionTemplate实例时,需要传入PlatformTransactionManager作为参数。
事务的执行位于TransactionTemplate实例的execute()方法中。
在TransactionTemplate实例的execute()方法中,需要一个org.springframework.transaction.support.TransactionCallback接口的实例作为参数。TransactionCallback接口的实例往往通过匿名内部类的方式给出,在匿名内部类中重写其doInTransaction()方法。
doInTransaction()方法会返回一个对象,作为事务执行的结果。所以,直接实现TransactionCallback接口适合于有返回结果的事务。
事务执行的过程中,如果发生异常,可以调用TransactionStatus的setRollbackOnly()方法回滚事务。
2) 对于事务的执行没有返回结果的情况,可以重写org.springframework.transaction.support.TransactionCallbackWithoutResult抽象类,并重写其doInTransactionWithoutResult()方法,如下:
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);
}
public Object someServiceMethod() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
public void doInTransaction<span style="font-family: Arial, Helvetica, sans-serif;">WithoutResult</span><span style="font-family: Arial, Helvetica, sans-serif;">(TransactionStatus status) {</span>
try {
updateOperation1();
UpdateOperation2();
} catch (SomeBusinessExeption ex) {
status.setRollbackOnly();
}
}
});
}
}
3) 上述示例中的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.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
this.transactionTemplate.setReadOnly(true);
this.transactionTemplate.setTimeout(30); // 30 seconds
// and so forth...
}
}
4) 大家可能已经注意到了,TransactionTemplate实例完全可以通过Spring Bean的方式注入,其在XML配置文件中的配置示例如下:
<bean id="sharedTransactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/>
<property name="propagationBehavior" value="PROPAGATION_REQUIRED"/>
<property name="readOnly" value="true"/>
<property name="timeout" value="30"/>
</bean>"
2.使用org.springframework.transaction.PlatformTransactionManager接口的实现类实现Spring的编程式事务
在代码中首先实例化PlatformTransactionManager接口的一个实现类,也可以通过Spring Bean的方式注入。
然后就可以通过PlatformTransactionManager实例的getTransaction()方法得到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);
说明,设置PlatformTransactionManager实例的事务参数用到了DefaultTransactionDefinition实例。
PlatformTransactionManager实例的注入可以参考本系列博文。