SpringBoot中的事务配置管理详解

 更新时间:2024年01月15日 10:13:16   作者:Mu_Mu是一只小白  
这篇文章主要介绍了SpringBoot中的事务配置管理详解,Spring Boot 默认的事务规则是遇到运行异常(RuntimeException)和程序错误(Error)才会回滚,但是抛出SQLException就无法回滚了,需要的朋友可以参考下

Spring Boot事务配置管理

场景:我们在开发企业应用时,由于数据操作在顺序执行的过程中,线上可能有各种无法预知的问题,

任何一步操作都有可能发生异常,异常则会导致后续的操作无法完成。此时由于业务逻辑并未正确的完

成,所以在之前操作过数据库的动作并不可靠,需要在这种情况下进行数据的回滚。

1. 导入依赖

springboot的事务管理需要导入spring-boot-starter-jdbc;而我们导入的mybatis-spring-boot-starter包含了它,所以无需重复导入;

 <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

2. 事务测试

1)mapper接口

@Insert("insert into tb_filminfo (typeid,filmname,ticketprice) values(#{typeid},#{filmname},#{ticketprice})")
    int insert(FilminfoPO po);

2)service接口

public interface IFilmInfoService {
    //插入一条记录
    public int insert(FilminfoPO po);

3)service实现类

@Service
public class FilmInfoServiceImpl implements IFilmInfoService {
   @Resource
    private FilmInfoMapper mapper;

    @Transactional
    @Override
    public int insert(FilminfoPO po) {

        return mapper.insert(po);
    }

4)controller类

@Controller
@RequestMapping("/film")
public class FilmInfoController {

   @Resource
    IFilmInfoService service;

    @RequestMapping("/insert")
    public String insert(FilminfoPO po) {
       if (po!=null) {
            int i = service.insert(po);
            return "success";
        } else {
            return "false";
        }
    }
}

当没有异常抛出时添加成功,有异常出现添加失败;

3. 事务处理的一些特殊情况

1)异常并没有被捕获到

异常并没有被 ”捕获“ 到,导致事务并没有回滚。

Spring Boot 默认的事务规则是遇到运行异常(RuntimeException)和程序 错误(Error)才会回滚。但是抛出 SQLException 就无法回滚了。

   @Transactional
    @Override
    public void insert(FilminfoPO po) throws SQLException {
        // 手动抛出异常
        mapper.insert(po);
        throw new SQLException("数据库异常");

虽然抛出异常但是数据插入成功;

解决方案:针对非运行时异常,如果要进行事务回滚的话,可以在 @Transactional 注解中使用 rollbackFor 属性来指定异常,比如 @Transactional(rollbackFor = Exception.class) ,这样就没有问题了,所以在实际项目中,一定要指定异常。

 @Transactional(rollbackFor = Exception.class)
    @Override
    public void insert(FilminfoPO po) throws SQLException {
        // 手动抛出异常
        mapper.insert(po);
        throw new SQLException("数据库异常");
    }

这样就插入失败了;

2)异常在方法中被捕获导致事务回滚失败

我们在处理异常时,有两种方式, 要么抛出去,让上一层来捕获处理;要么把异常 try catch 掉,在异常出现的地方给处理掉。就因为有 这中 try…catch,所以导致异常被 ”吃“ 掉,事务无法回滚。

    @Transactional
    @Override
    public int insert(FilminfoPO po) {
        try {
            int i = 1 / 0;
        } catch (Exception e) {
            e.getMessage();
        }
        return mapper.insert(po);
    }

记录成功被插入;

解决方法:直接往上抛,给上一层来处理即可

3)事务的范围 冲突导致回滚失败

许多业务需要在高并发的情况下保证数据唯一性所比要加synchronized关键字如一个数据库中,针对某个用户,只有一条记录,下一个插入动作过来,会先判断该数据库 中有没有相同的用户,如果有就不插入,就更新,没有才插入,所以理论上,数据库中永远就一条同一 用户信息,不会出现同一数据库中插入了两条相同用户的信息。

    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized void insert(FilminfoPO po) throws SQLException {
        // 手动抛出异常
        mapper.insert(po);
     
    }

但是在压测时,数据库中确实可能有两条同一用户的信息,分析其原因,在于事务的

范围和锁的范围问题。

在执行该方法开始时,事务启动,执行 完了后,事务关闭。但是 synchronized 没有起作用,其实根本原因是因为事务的范围比锁的范围大。 也就是说,在加锁的那部分代码执行完之后,锁释放掉了,但是事务还没结束,此时另一个线程进来 了,事务没结束的话,第二个线程进来时,数据库的状态和第一个线程刚进来是一样的。即由于mysql Innodb引擎的默认隔离级别是可重复读(在同一个事务里,SELECT的结果是事务开始时时间点的状 态),线程二事务开始的时候,线程一还没提交完成,导致读取的数据还没更新。第二个线程也做了插 入动作,导致了脏数据。

解决方案:

​ 1.把事务去掉即可(不推荐);

​ 2. 在调用该 service 的地方加锁,保证锁 的范围比事务的范围大即可。

到此这篇关于SpringBoot中的事务配置管理详解的文章就介绍到这了,更多相关SpringBoot事务配置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot整合JPA使用多个数据源的方法步骤

    Spring Boot整合JPA使用多个数据源的方法步骤

    这篇文章主要给大家介绍了关于Spring Boot整合JPA使用多个数据源的方法步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • Java实现高并发秒杀的七种方式

    Java实现高并发秒杀的七种方式

    本文主要介绍了Java实现高并发秒杀的六种方式,包括使用缓存、数据库乐观锁、数据库悲观锁、分布式锁、队列限流、令牌桶算法和限流器,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Spring Cloud Alibaba之Sentinel实现熔断限流功能

    Spring Cloud Alibaba之Sentinel实现熔断限流功能

    这篇文章主要介绍了Spring Cloud Alibaba之Sentinel,这里使用阿里的sentinel来实现熔断限流功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • Mybatis中 mapper-locations和@MapperScan的作用

    Mybatis中 mapper-locations和@MapperScan的作用

    这篇文章主要介绍了Mybatis中 mapper-locations和@MapperScan的作用,mybatis.mapper-locations在SpringBoot配置文件中使用,作用是扫描Mapper接口对应的XML文件,需要的朋友可以参考下
    2023-05-05
  • Java编程几个循环实例代码分享

    Java编程几个循环实例代码分享

    这篇文章主要介绍了Java编程几个循环实例代码分享,多看多练,小编觉得还是挺不错的,这里分享给大家,供需要的朋友参考。
    2017-10-10
  • 浅谈java异常处理之空指针异常

    浅谈java异常处理之空指针异常

    下面小编就为大家带来一篇浅谈java异常处理之空指针异常。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-10-10
  • Java实现超大Excel文件解析(XSSF,SXSSF,easyExcel)

    Java实现超大Excel文件解析(XSSF,SXSSF,easyExcel)

    这篇文章主要为大家详细介绍了如何利用Java语言实现超大Excel文件解析(XSSF,SXSSF,easyExcel)以及速度的对比,感兴趣的可以了解一下
    2022-07-07
  • SpringBoot中的健康检查详解

    SpringBoot中的健康检查详解

    这篇文章主要介绍了SpringBoot中的健康检查详解,健康检查是一种用来确保应用程序和其所依赖的服务的状态正常的机制,在本文中,我们将探讨SpringBoot中的健康检查是什么以及如何使用它来监视应用程序的状态,需要的朋友可以参考下
    2023-07-07
  • java + dom4j.jar提取xml文档内容

    java + dom4j.jar提取xml文档内容

    这篇文章主要为大家详细介绍了java + dom4j.jar提取xml文档内容,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • MyBatisPlus PaginationInterceptor分页插件的使用详解

    MyBatisPlus PaginationInterceptor分页插件的使用详解

    这篇文章主要介绍了MyBatisPlus PaginationInterceptor分页插件的使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03

最新评论