SpringBoot中的手动提交事务

 更新时间:2024年09月29日 10:11:42   作者:爱码猿  
在Spring框架中使用@Transactional注解通常管理事务,但在多线程环境下此方法失效,本文讨论了手动事务的必要性及其实现方式,探讨了Spring的七种事务传播行为和数据库的四大特性与隔离级别,了解这些可以帮助开发者在无法使用声明式事务时

今天在工作中遇到了一个spring事务的问题:

在service方法内需要通过线程去执行添加用户积分和用户积分日志的情况,试了下通过@Transactional声明式事务不起作用,只能使用手动事务去控制

因此写了这篇博客,记录一下这个情况

一、事务的重要性

相信在实际开发过程中,都有很深的了解了。

但是存在一个问题我们经常在开发的时候一般情况下都是用的注解的方式来进行事务的控制,说白了基于spring的7种事务控制方式来进行事务的之间的协调。

二、spring的7中事务传播行为

Propagation.REQUIRED代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则自己新建事务,
Propagation.SUPPORTS代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则该方法在非事务的上下文中执行
Propagation.MANDATORY代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则抛出异常
Propagation.REQUIRES_NEW创建一个新的事务上下文,如果当前方法的调用者已经有了事务,则挂起调用者的事务,这两个事务不处于同一上下文,如果各自发生异常,各自回滚
Propagation.NOT_SUPPORTED该方法以非事务的状态执行,如果调用该方法的调用者有事务则先挂起调用者的事务
Propagation.NEVER该方法以非事务的状态执行,如果调用者存在事务,则抛出异常
Propagation.NESTED如果当前上下文中存在事务,则以嵌套事务执行该方法,也就说,这部分方法是外部方法的一部分,调用者回滚,则该方法回滚,但如果该方法自己发生异常,则自己回滚,不会影响外部事务,如果不存在事务,则与PROPAGATION_REQUIRED一样

三、数据库四大特性和MySQL事务的隔离级别

1)四大特性

a、原子性(Atomicity)  

原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。

b、 一致性(Consistency)  

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

c、隔离性(Isolation)  

隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

d、 持久性(Durability)  

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

2)隔离级别

a、脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。(读取未提交的数据)

b、不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。(边读边写)

c、幻读指两个事务同时发生,两个事务修改数据,读到的数据不是自己开始修改的数据。幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体。(同时写,同时读)

3)数据库事务级别

默认使用Repeatable read级别,列表级别从下往上级别越低。

查看级别

select @@tx_isolation;

四、写上面spring事务和数据库事务隔离级别

主要的目的就是了解事务之间存在的传递关系,这样在控制的时候,spring会通过事务与事务之间关系,来达到回滚或者提交的效果。

五、如果在没有办法使用注解的时候(比如多线程等)

就要使用手动的方式来做事务管理了,这也就是编程式的事务管理。

1)首先加入注解

这就是spring的jdbc框架中提供的事务管理方式

    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

2)看一下源码

(DataSourceTransactionManagerAutoConfiguration.class、TransactionTemplate.class)

        @Bean
        @ConditionalOnMissingBean({PlatformTransactionManager.class})
        public DataSourceTransactionManager transactionManager(DataSourceProperties properties) {
            DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource);
            if (this.transactionManagerCustomizers != null) {
                this.transactionManagerCustomizers.customize(transactionManager);
            }

            return transactionManager;
        }

备注:有兴趣可以了解一下DataSourceTransactionManager的写法和原理。

        @Bean
        @ConditionalOnMissingBean
        public TransactionTemplate transactionTemplate() {
            return new TransactionTemplate(this.transactionManager);
        }

注意,这里的所有事务传播方式包括处理,都需要自己手动去处理。

3)编写方式

TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
platformTransactionManager.commit(transactionStatus);
platformTransactionManager.rollback(transactionStatus);

说明:这里开发事务过后,返回一个事务状态,这个状态记录了东西,用来控制事务的管理,当然,多个事务之间的控制需要人为控制。

4)编程式的事务控制经量少用

因为控制程度上面来说spring的方式还是来的更加不错,编程式的方式,更多用于在需要事务的时候,没有办法加入事务,才采取手动控制事务的方式。

使用示例 :

1 在service内注入 这两个bean 
@Autowired
private PlatformTransactionManager platformTransactionManager;

@Autowired
private TransactionDefinition transactionDefinition;

2在 service方法内创建TransactionStatus
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
通过 platformTransactionManager.commit(transactionStatus); 提交事务
通过 platformTransactionManager.rollback(transactionStatus); 回滚事务 

示例代码: 

@Autowired
private PlatformTransactionManager platformTransactionManager;

@Autowired
private TransactionDefinition transactionDefinition;

public void b(){
    TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);

    UserIntegralInfo info = new UserIntegralInfo();
    info.setUserId(1L);
    info.setPoint(1);
    info.setOp("");
    info.setCurrIntegral(1);
    integralMapper.insert(info);
    platformTransactionManager.commit(transactionStatus);
    throw new RuntimeException();
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot工程启动时自动执行任务实现方式

    SpringBoot工程启动时自动执行任务实现方式

    在SpringBoot中,推荐通过ApplicationRunner/CommandLineRunner或ApplicationReadyEvent监听实现启动时自动执行MQ任务,确保应用完全就绪,避免依赖未初始化问题,同时需配置连接池、重试机制及多环境控制,保障系统稳定与资源优雅关闭
    2025-09-09
  • eclipse springboot工程打war包方法及再Tomcat中运行的方法

    eclipse springboot工程打war包方法及再Tomcat中运行的方法

    这篇文章主要介绍了eclipse springboot工程打war包方法及再Tomcat中运行的方法,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • SpringBoot整合接口管理工具Swagger

    SpringBoot整合接口管理工具Swagger

    ​ Swagger是一系列 RESTful API的工具,通过Swagger可以获得项目的⼀种交互式文档,客户端SDK的自动生成等功能。本文通过代码示例详细介绍了SpringBoot整合接口管理工具Swagger,需要的朋友可以借鉴参考
    2023-04-04
  • 详解Java编程中线程的挂起、恢复和终止的方法

    详解Java编程中线程的挂起、恢复和终止的方法

    这篇文章主要介绍了详解Java编程中线程的挂起、恢复和终止的方法,线程是Java学习中的重点和难点知识,需要的朋友可以参考下
    2015-09-09
  • Java那点事——StringBuffer与StringBuilder原理与区别

    Java那点事——StringBuffer与StringBuilder原理与区别

    本文给大家分享StringBuffer与StringBuilder的区别,它们的应用场景是什么?非常不错,面试考官经常考的一个问题,有需要的朋友跟着脚本之家小编一起学习吧
    2016-06-06
  • Java实现解数独的小程序

    Java实现解数独的小程序

    最近在学习Java,然后上个月迷上了九宫格数独,玩了几天,觉得实在有趣,就想着能不能用编程来解决,于是就自己写了个,还真解决了。下面这篇文章就给大家主要介绍了Java实现解数独的小程序,需要的朋友可以参考借鉴。
    2017-01-01
  • SpringBoot读取yaml文件操作详解

    SpringBoot读取yaml文件操作详解

    YAML 是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言),本文给大家介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • SpringBoot中使用MongoDB的连接池配置全过程

    SpringBoot中使用MongoDB的连接池配置全过程

    这篇文章主要介绍了SpringBoot中使用MongoDB的连接池配置全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06
  • Tomcat安装配置及Eclipse配置详解

    Tomcat安装配置及Eclipse配置详解

    给大家介绍一下Tomcat安装配置及Eclipse配置的全部图文过程,如果你对这个还有不明白,一起跟着小编学习下。
    2017-11-11
  • Java编程Socket实现多个客户端连接同一个服务端代码

    Java编程Socket实现多个客户端连接同一个服务端代码

    这篇文章主要介绍了Java编程Socket实现多个客户端连接同一个服务端代码,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11

最新评论