写点什么

Spring 5 中文解析数据存储篇 - 编程式事物管理

用户头像
青年IT男
关注
发布于: 2020 年 09 月 22 日
Spring 5 中文解析数据存储篇-编程式事物管理

Spring核心篇章:



Spring 5 中文解析之核心篇-IoC容器



Spring 5 中文解析核心篇-IoC容器之依赖关系



Spring 5 中文解析核心篇-IoC容器之Bean作用域



Spring 5 中文解析核心篇-IoC容器之自定义Bean性质



Spring 5 中文解析核心篇-IoC容器之BeanDefinition继承与容器拓展点



Spring 5 中文解析核心篇-IoC容器之基于注解的容器配置



Spring 5 中文解析核心篇-IoC容器之类路径扫描和组件管理



Spring 5 中文解析核心篇-IoC容器之JSR330标准注解



Spring 5 中文解析核心篇-IoC容器之基于Java容器配置



Spring 5 中文解析核心篇-IoC容器之Environment抽象



Spring 5 中文解析核心篇-IoC容器之ApplicationContext与BeanFactory



Spring 5 中文解析核心篇-IoC容器之Resources



Spring 5 中文解析核心篇-IoC容器之数据校验、数据绑定和类型转换



Spring 5 中文解析核心篇-IoC容器之SpEL表达式



Spring 5 中文解析核心篇-IoC容器之AOP编程(上)



Spring 5 中文解析核心篇-IoC容器之AOP编程(下)



Spring 5 中文解析核心篇-IoC容器之Spring AOP API



Spring测试篇章:



Spring 5 中文解析测试篇-Spring测试



Spring 5 中文解析核心篇-集成测试之概要和集成测试注解



Spring 5 中文解析核心篇-集成测试之TestContext(上)



Spring 5 中文解析核心篇-集成测试之TestContext(中)



Spring 5 中文解析测试篇-集成测试之TestContext(下)



Spring 5 中文解析测试篇-Spring MVC测试框架



Spring 5 中文解析测试篇-WebTestClient



Spring存储篇章:



Spring 5 中文解析数据存储篇-Spring框架的事物支持模型的优势



Spring 5 中文解析数据存储篇-事务同步和声明式事物管理



Spring 5 中文解析数据存储篇-@Transactional使用



完整电子书地址



Spring框架通过使用以下两种方式提供编程式事务管理的方法:



  • TransactionTemplateTransactionalOperator

  • TransactionManager直接实现



Spring团队通常建议对命令式流程中的编程式事务管理推荐使用TransactionTemplate,对响应性代码推荐TransactionalOperator。第二种方法类似于使用JTA UserTransaction API,尽管异常处理的麻烦程度较小。



1.5.1 使用TransactionTemplate



TransactionTemplate采用与其他Spring模板(如JdbcTemplate)相同的方法。它使用一种回调方法(使应用程序代码不必进行样板获取和释放事务性资源),并生成意向驱动的代码,因为你的代码仅专注于你要执行的操作。



如下面的示例所示,使用TransactionTemplate完全将你与Spring的事务基础结构和api结合在一起。编程式事务管理是否适合你的开发需求是你必须自己做的决定。



必须在事务上下文中运行并且显式使用TransactionTemplate的应用程序代码类似于下一个示例。作为应用程序开发人员,你可以编写TransactionCallback实现(通常表示为匿名内部类),其中包含你需要在事务上下文中运行的代码。然后,你可以将自定义TransactionCallback的实例传递给TransactionTemplate上暴露的execute(..)方法。以下示例显示了如何执行此操作:



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) {        this.transactionTemplate = new TransactionTemplate(transactionManager);   }​    public Object someServiceMethod() {        return transactionTemplate.execute(new TransactionCallback() {            // the code in this method runs 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 (SomeBusinessException ex) {            status.setRollbackOnly();       }   }});



指定事物配置



你可以通过编程方式或配置方式在TransactionTemplate上指定事务设置(例如传播模式、隔离级别、超时等)。默认情况下,TransactionTemplate实例具有默认的事务设置。以下示例显示了针对特定TransactionTemplate的事务设置的编程自定义:



public class SimpleService implements Service {​    private final TransactionTemplate transactionTemplate;​    public SimpleService(PlatformTransactionManager transactionManager) {        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...   }}



以下示例通过使用Spring XML配置来定义带有一些自定义事务设置的TransactionTemplate



<bean id="sharedTransactionTemplate"        class="org.springframework.transaction.support.TransactionTemplate">    <property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/>    <property name="timeout" value="30"/></bean>



然后,你可以将sharedTransactionTemplate注入到所需的服务中。



最后,TransactionTemplate类的实例是线程安全的,因为这些实例不维护任何对话状态。但是,TransactionTemplate实例确实会维护配置状态。因此,尽管许多类可以共享一个TransactionTemplate实例,但是如果一个类需要使用具有不同设置(例如,不同的隔离级别)的TransactionTemplate,则需要创建两个不同的TransactionTemplate实例。



参考代码:org.liyong.dataaccess.starter.TransactionTemplateIocContainer



1.5.2 使用TransactionOperator



TransactionOperator遵循类似于其他响应式操作符的设计。它使用一种回调方法(使应用程序代码不必进行模版获取和释放事务性资源),并生成意向驱动的代码,因为你的代码仅专注于你要执行的操作。



如以下示例所示,使用TransactionOperator绝对可以使你与Spring的事务基础结构和API结合。编程式事务管理是否适合你的开发需求是你必须自己做的决定。



必须在事务上下文中运行并且显式使用TransactionOperator的应用程序代码类似于下一个示例:



public class SimpleService implements Service {​    // single TransactionOperator shared amongst all methods in this instance    private final TransactionalOperator transactionalOperator;​    // use constructor-injection to supply the ReactiveTransactionManager    public SimpleService(ReactiveTransactionManager transactionManager) {        this.transactionOperator = TransactionalOperator.create(transactionManager);   }​    public Mono<Object> someServiceMethod() {​        // the code in this method runs in a transactional context​        Mono<Object> update = updateOperation1();​        return update.then(resultOfUpdateOperation2).as(transactionalOperator::transactional);   }}



TransactionalOperator可以通过两种方式使用:



  • 使用Reactor类型的操作符样式(mono.as(transactionalOperator :: transactional))

  • 其他所有情况的回调样式(transactionalOperator.execute(TransactionCallback <T>))



回调中的代码可以通过在提供的ReactiveTransaction对象上调用setRollbackOnly()方法来回滚事务,如下所示:



transactionalOperator.execute(new TransactionCallback<>() {​    public Mono<Object> doInTransaction(ReactiveTransaction status) {        return updateOperation1().then(updateOperation2)                   .doOnError(SomeBusinessException.class, e -> status.setRollbackOnly());       }   }});



取消信号



在响应式流中,Subscriber可以取消其Subscription并停止其PublisherProject Reactor以及其他库中的操作符,例如next()take(long)timeout(Duration)等,都可以发出取消操作。没有办法知道取消的原因,无论是由于错误还是仅仅是出于进一步消费的兴趣,并且在5.2版中,TransactionalOperator默认在取消时提交事务。在版本5.3中,这种行为将发生改变,事务将在取消时回滚,以创建可靠的和确定性的结果。因此,重要的是要考虑从事务发布服务器下游使用的操作符。特别是在Flux或其他多值Publisher的情况下,必须使用完整的输出以允许事务完成。



指定事物配置



你可以为TransactionalOperator指定事务设置(例如传播模式、隔离级别、超时等)。默认情况下,TransactionalOperator实例具有默认的事务设置。以下示例显示了针对特定TransactionalOperator的事务设置的自定义:



public class SimpleService implements Service {​    private final TransactionalOperator transactionalOperator;​    public SimpleService(ReactiveTransactionManager transactionManager) {        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();​        // the transaction settings can be set here explicitly if so desired        definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);        definition.setTimeout(30); // 30 seconds        // and so forth...​        this.transactionalOperator = TransactionalOperator.create(transactionManager, definition);   }}



1.5.3 使用TransactionManager



以下各节说明命令式和响应式事务管理器的用法。



使用PlatformTransactionManager



对于命令式事务,可以直接使用org.springframework.transaction.PlatformTransactionManager来管理事务。为此,通过bean引用将你使用的PlatformTransactionManager的实现传递给bean。然后,通过使用TransactionDefinitionTransactionStatus对象,可以启动事务、回滚和提交。以下示例显示了如何执行此操作:



DefaultTransactionDefinition def = new DefaultTransactionDefinition();// explicitly setting the transaction name is something that can be done only programmaticallydef.setName("SomeTxName");def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);​TransactionStatus status = txManager.getTransaction(def);try {    // put your business logic here}catch (MyException ex) {    txManager.rollback(status);    throw ex;}txManager.commit(status);



使用ReactiveTransactionManager



使用响应式事务时,可以直接使用org.springframework.transaction.ReactiveTransactionManager来管理事务。为此,请通过bean引用将你使用的ReactiveTransactionManager的实现传递给bean。然后,通过使用TransactionDefinitionReactiveTransaction对象,可以启动事务、回滚和提交。以下示例显示了如何执行此操作:



DefaultTransactionDefinition def = new DefaultTransactionDefinition();// explicitly setting the transaction name is something that can be done only programmaticallydef.setName("SomeTxName");def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);​Mono<ReactiveTransaction> reactiveTx = txManager.getReactiveTransaction(def);​reactiveTx.flatMap(status -> {​    Mono<Object> tx = ...; // put your business logic here​    return tx.then(txManager.commit(status))           .onErrorResume(ex -> txManager.rollback(status).then(Mono.error(ex)));});



Spring框架通过使用以下两种方式提供编程式事务管理的方法:



  • TransactionTemplateTransactionalOperator

  • TransactionManager直接实现



Spring团队通常建议对命令式流程中的编程式事务管理推荐使用TransactionTemplate,对响应性代码推荐TransactionalOperator。第二种方法类似于使用JTA UserTransaction API,尽管异常处理的麻烦程度较小。



1.5.1 使用TransactionTemplate



TransactionTemplate采用与其他Spring模板(如JdbcTemplate)相同的方法。它使用一种回调方法(使应用程序代码不必进行样板获取和释放事务性资源),并生成意向驱动的代码,因为你的代码仅专注于你要执行的操作。



如下面的示例所示,使用TransactionTemplate完全将你与Spring的事务基础结构和api结合在一起。编程式事务管理是否适合你的开发需求是你必须自己做的决定。



必须在事务上下文中运行并且显式使用TransactionTemplate的应用程序代码类似于下一个示例。作为应用程序开发人员,你可以编写TransactionCallback实现(通常表示为匿名内部类),其中包含你需要在事务上下文中运行的代码。然后,你可以将自定义TransactionCallback的实例传递给TransactionTemplate上暴露的execute(..)方法。以下示例显示了如何执行此操作:



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) {        this.transactionTemplate = new TransactionTemplate(transactionManager);   }​    public Object someServiceMethod() {        return transactionTemplate.execute(new TransactionCallback() {            // the code in this method runs 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 (SomeBusinessException ex) {            status.setRollbackOnly();       }   }});



指定事物配置



你可以通过编程方式或配置方式在TransactionTemplate上指定事务设置(例如传播模式、隔离级别、超时等)。默认情况下,TransactionTemplate实例具有默认的事务设置。以下示例显示了针对特定TransactionTemplate的事务设置的编程自定义:



public class SimpleService implements Service {​    private final TransactionTemplate transactionTemplate;​    public SimpleService(PlatformTransactionManager transactionManager) {        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...   }}



以下示例通过使用Spring XML配置来定义带有一些自定义事务设置的TransactionTemplate



<bean id="sharedTransactionTemplate"        class="org.springframework.transaction.support.TransactionTemplate">    <property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/>    <property name="timeout" value="30"/></bean>



然后,你可以将sharedTransactionTemplate注入到所需的服务中。



最后,TransactionTemplate类的实例是线程安全的,因为这些实例不维护任何对话状态。但是,TransactionTemplate实例确实会维护配置状态。因此,尽管许多类可以共享一个TransactionTemplate实例,但是如果一个类需要使用具有不同设置(例如,不同的隔离级别)的TransactionTemplate,则需要创建两个不同的TransactionTemplate实例。



参考代码:org.liyong.dataaccess.starter.TransactionTemplateIocContainer



1.5.2 使用TransactionOperator



TransactionOperator遵循类似于其他响应式操作符的设计。它使用一种回调方法(使应用程序代码不必进行模版获取和释放事务性资源),并生成意向驱动的代码,因为你的代码仅专注于你要执行的操作。



如以下示例所示,使用TransactionOperator绝对可以使你与Spring的事务基础结构和API结合。编程式事务管理是否适合你的开发需求是你必须自己做的决定。



必须在事务上下文中运行并且显式使用TransactionOperator的应用程序代码类似于下一个示例:



public class SimpleService implements Service {​    // single TransactionOperator shared amongst all methods in this instance    private final TransactionalOperator transactionalOperator;​    // use constructor-injection to supply the ReactiveTransactionManager    public SimpleService(ReactiveTransactionManager transactionManager) {        this.transactionOperator = TransactionalOperator.create(transactionManager);   }​    public Mono<Object> someServiceMethod() {​        // the code in this method runs in a transactional context​        Mono<Object> update = updateOperation1();​        return update.then(resultOfUpdateOperation2).as(transactionalOperator::transactional);   }}



TransactionalOperator可以通过两种方式使用:



  • 使用Reactor类型的操作符样式(mono.as(transactionalOperator :: transactional))

  • 其他所有情况的回调样式(transactionalOperator.execute(TransactionCallback <T>))



回调中的代码可以通过在提供的ReactiveTransaction对象上调用setRollbackOnly()方法来回滚事务,如下所示:



transactionalOperator.execute(new TransactionCallback<>() {​    public Mono<Object> doInTransaction(ReactiveTransaction status) {        return updateOperation1().then(updateOperation2)                   .doOnError(SomeBusinessException.class, e -> status.setRollbackOnly());       }   }});



取消信号



在响应式流中,Subscriber可以取消其Subscription并停止其PublisherProject Reactor以及其他库中的操作符,例如next()take(long)timeout(Duration)等,都可以发出取消操作。没有办法知道取消的原因,无论是由于错误还是仅仅是出于进一步消费的兴趣,并且在5.2版中,TransactionalOperator默认在取消时提交事务。在版本5.3中,这种行为将发生改变,事务将在取消时回滚,以创建可靠的和确定性的结果。因此,重要的是要考虑从事务发布服务器下游使用的操作符。特别是在Flux或其他多值Publisher的情况下,必须使用完整的输出以允许事务完成。



指定事物配置



你可以为TransactionalOperator指定事务设置(例如传播模式、隔离级别、超时等)。默认情况下,TransactionalOperator实例具有默认的事务设置。以下示例显示了针对特定TransactionalOperator的事务设置的自定义:



public class SimpleService implements Service {​    private final TransactionalOperator transactionalOperator;​    public SimpleService(ReactiveTransactionManager transactionManager) {        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();​        // the transaction settings can be set here explicitly if so desired        definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);        definition.setTimeout(30); // 30 seconds        // and so forth...​        this.transactionalOperator = TransactionalOperator.create(transactionManager, definition);   }}



1.5.3 使用TransactionManager



以下各节说明命令式和响应式事务管理器的用法。



使用PlatformTransactionManager



对于命令式事务,可以直接使用org.springframework.transaction.PlatformTransactionManager来管理事务。为此,通过bean引用将你使用的PlatformTransactionManager的实现传递给bean。然后,通过使用TransactionDefinitionTransactionStatus对象,可以启动事务、回滚和提交。以下示例显示了如何执行此操作:



DefaultTransactionDefinition def = new DefaultTransactionDefinition();// explicitly setting the transaction name is something that can be done only programmaticallydef.setName("SomeTxName");def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);​TransactionStatus status = txManager.getTransaction(def);try {    // put your business logic here}catch (MyException ex) {    txManager.rollback(status);    throw ex;}txManager.commit(status);



使用ReactiveTransactionManager



使用响应式事务时,可以直接使用org.springframework.transaction.ReactiveTransactionManager来管理事务。为此,请通过bean引用将你使用的ReactiveTransactionManager的实现传递给bean。然后,通过使用TransactionDefinitionReactiveTransaction对象,可以启动事务、回滚和提交。以下示例显示了如何执行此操作:



DefaultTransactionDefinition def = new DefaultTransactionDefinition();// explicitly setting the transaction name is something that can be done only programmaticallydef.setName("SomeTxName");def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);​Mono<ReactiveTransaction> reactiveTx = txManager.getReactiveTransaction(def);​reactiveTx.flatMap(status -> {​    Mono<Object> tx = ...; // put your business logic here​    return tx.then(txManager.commit(status))           .onErrorResume(ex -> txManager.rollback(status).then(Mono.error(ex)));});



作者



个人从事金融行业,就职过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就职于某银行负责统一支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。同时也热衷于技术分享创立公众号和博客站点对知识体系进行分享。关注公众号:青年IT男 获取最新技术文章推送!



博客地址: http://youngitman.tech



CSDN: https://blog.csdn.net/liyong1028826685



微信公众号: 

 技术交流群: 



发布于: 2020 年 09 月 22 日阅读数: 41
用户头像

青年IT男

关注

站在巨人肩上看得更远! 2018.04.25 加入

从事金融行业,就职过易极付、思建科技、网约车平台等一流技术团队,目前就职于银行负责支付系统建设。对金融行业有强烈的爱好。实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域

评论

发布
暂无评论
Spring 5 中文解析数据存储篇-编程式事物管理