精品推荐:
Spring框架通过使用以下两种方式提供编程式事务管理的方法:
TransactionTemplate或TransactionalOperator
TransactionManager直接实现
Spring团队通常建议对命令式流程中的编程式事务管理推荐使用TransactionTemplate,对响应性代码推荐TransactionalOperator。第二种方法类似于使用JTAUserTransactionAPI,尽管异常处理的麻烦程度较小。
1.5.1使用TransactionTemplateTransactionTemplate采用与其他Spring模板(如JdbcTemplate)相同的方法。它使用一种回调方法(使应用程序代码不必进行样板获取和释放事务性资源),并生成意向驱动的代码,因为你的代码仅专注于你要执行的操作。
如下面的示例所示,使用TransactionTemplate完全将你与Spring的事务基础结构和api结合在一起。编程式事务管理是否适合你的开发需求是你必须自己做的决定。
必须在事务上下文中运行并且显式使用TransactionTemplate的应用程序代码类似于下一个示例。作为应用程序开发人员,你可以编写TransactionCallback实现(通常表示为匿名内部类),其中包含你需要在事务上下文中运行的代码。然后,你可以将自定义TransactionCallback的实例传递给TransactionTemplate上暴露的execute(..)方法。以下示例显示了如何执行此操作:
publicclassSimpleServiceimplementsService{
//singleTransactionTemplatesharedamongstallmethodsinthisinstance
privatefinalTransactionTemplatetransactionTemplate;
//useconstructor-injectiontosupplythePlatformTransactionManager
publicSimpleService(PlatformTransactionManagertransactionManager){
this.transactionTemplate=newTransactionTemplate(transactionManager);
}
publicObjectsomeServiceMethod(){
returntransactionTemplate.execute(newTransactionCallback(){
//thecodeinthismethodrunsinatransactionalcontext
publicObjectdoInTransaction(TransactionStatusstatus){
updateOperation1();
returnresultOfUpdateOperation2();
}
});
}
}
如果没有返回值,则可以将便捷的TransactionCallbackWithoutResult类与匿名类一起使用,如下所示:
transactionTemplate.execute(newTransactionCallbackWithoutResult(){
protectedvoiddoInTransactionWithoutResult(TransactionStatusstatus){
updateOperation1();
updateOperation2();
}
});
回调中的代码可以通过在提供的TransactionStatus对象上调用setRollbackOnly()方法来回滚事务,如下所示:
transactionTemplate.execute(newTransactionCallbackWithoutResult(){
protectedvoiddoInTransactionWithoutResult(TransactionStatusstatus){
try{
updateOperation1();
updateOperation2();
}catch(SomeBusinessExceptionex){
status.setRollbackOnly();
}
}
});
指定事物配置
你可以通过编程方式或配置方式在TransactionTemplate上指定事务设置(例如传播模式、隔离级别、超时等)。默认情况下,TransactionTemplate实例具有默认的事务设置。以下示例显示了针对特定TransactionTemplate的事务设置的编程自定义:
publicclassSimpleServiceimplementsService{
privatefinalTransactionTemplatetransactionTemplate;
publicSimpleService(PlatformTransactionManagertransactionManager){
this.transactionTemplate=newTransactionTemplate(transactionManager);
//thetransactionsettingscanbesethereexplicitlyifsodesired
this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
this.transactionTemplate.setTimeout(30);//30seconds
//andsoforth...
}
}
以下示例通过使用SpringXML配置来定义带有一些自定义事务设置的TransactionTemplate:
beanid="sharedTransactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate"
propertyname="isolationLevelName"value="ISOLATION_READ_UNCOMMITTED"/
propertyname="timeout"value="30"/
/bean
然后,你可以将sharedTransactionTemplate注入到所需的服务中。
最后,TransactionTemplate类的实例是线程安全的,因为这些实例不维护任何对话状态。但是,TransactionTemplate实例确实会维护配置状态。因此,尽管许多类可以共享一个TransactionTemplate实例,但是如果一个类需要使用具有不同设置(例如,不同的隔离级别)的TransactionTemplate,则需要创建两个不同的TransactionTemplate实例。
参考代码:org.liyong.dataaccess.starter.TransactionTemplateIocContainer
1.5.2使用TransactionOperatorTransactionOperator遵循类似于其他响应式操作符的设计。它使用一种回调方法(使应用程序代码不必进行模版获取和释放事务性资源),并生成意向驱动的代码,因为你的代码仅专注于你要执行的操作。
如以下示例所示,使用TransactionOperator绝对可以使你与Spring的事务基础结构和API结合。编程式事务管理是否适合你的开发需求是你必须自己做的决定。
必须在事务上下文中运行并且显式使用TransactionOperator的应用程序代码类似于下一个示例:
publicclassSimpleServiceimplementsService{
//singleTransactionOperatorsharedamongstallmethodsinthisinstance
privatefinalTransactionalOperatortransactionalOperator;
//useconstructor-injectiontosupplytheReactiveTransactionManager
publicSimpleService(ReactiveTransactionManagertransactionManager){
this.transactionOperator=TransactionalOperator.create(transactionManager);
}
publicMonoObjectsomeServiceMethod(){
//thecodeinthismethodrunsinatransactionalcontext
MonoObjectupdate=updateOperation1();
returnupdate.then(resultOfUpdateOperation2).as(transactionalOperator::transactional);
}
}
TransactionalOperator可以通过两种方式使用:
使用Reactor类型的操作符样式(mono.as(transactionalOperator::transactional))
其他所有情况的回调样式(transactionalOperator.execute(TransactionCallbackT))
回调中的代码可以通过在提供的ReactiveTransaction对象上调用setRollbackOnly()方法来回滚事务,如下所示:
transactionalOperator.execute(newTransactionCallback(){
publicMonoObjectdoInTransaction(ReactiveTransactionstatus){
returnupdateOperation1().then(updateOperation2)
.doOnError(SomeBusinessException.class,e-status.setRollbackOnly());
}
}
});
取消信号
在响应式流中,Subscriber可以取消其Subscription并停止其Publisher。ProjectReactor以及其他库中的操作符,例如next()、take(long)、timeout(Duration)等,都可以发出取消操作。没有办法知道取消的原因,无论是由于错误还是仅仅是出于进一步消费的兴趣,并且在5.2版中,TransactionalOperator默认在取消时提交事务。在版本5.3中,这种行为将发生改变,事务将在取消时回滚,以创建可靠的和确定性的结果。因此,重要的是要考虑从事务发布服务器下游使用的操作符。特别是在Flux或其他多值Publisher的情况下,必须使用完整的输出以允许事务完成。
指定事物配置
你可以为TransactionalOperator指定事务设置(例如传播模式、隔离级别、超时等)。默认情况下,TransactionalOperator实例具有默认的事务设置。以下示例显示了针对特定TransactionalOperator的事务设置的自定义:
publicclassSimpleServiceimplementsService{
privatefinalTransactionalOperatortransactionalOperator;
publicSimpleService(ReactiveTransactionManagertransactionManager){
DefaultTransactionDefinitiondefinition=newDefaultTransactionDefinition();
//thetransactionsettingscanbesethereexplicitlyifsodesired
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
definition.setTimeout(30);//30seconds
//andsoforth...
this.transactionalOperator=TransactionalOperator.create(transactionManager,definition);
}
}1.5.3使用TransactionManager
以下各节说明命令式和响应式事务管理器的用法。
使用PlatformTransactionManager
对于命令式事务,可以直接使用org.springframework.transaction.PlatformTransactionManager来管理事务。为此,通过bean引用将你使用的PlatformTransactionManager的实现传递给bean。然后,通过使用TransactionDefinition和TransactionStatus对象,可以启动事务、回滚和提交。以下示例显示了如何执行此操作:
DefaultTransactionDefinitiondef=newDefaultTransactionDefinition();
//explicitlysettingthetransactionnameissomethingthatcanbedoneonlyprogrammatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatusstatus=txManager.getTransaction(def);
try{
//putyourbusinesslogichere
}
catch(MyExceptionex){
txManager.rollback(status);
throwex;
}
txManager.