spring声明式事务 @Transactional 不回滚的多种情况以及解决方案

yizhihongxing

下面我将详细讲解“spring声明式事务 @Transactional 不回滚的多种情况以及解决方案”。

一、@Transactional不回滚的多种情况

1.1 默认回滚规则

  • 默认情况下,Spring会对所有运行时异常进行回滚。也就是说,只有在方法中抛出RuntimeException及其子类异常时,才会导致事务回滚。
  • 对于受检异常(即继承自Exception的异常),Spring不会自动回滚。

1.2 编程式事务管理

  • 在使用编程式事务管理时,如果没有手动设置任何异常回滚,则不会触发回滚。
  • 如果手动设置回滚条件,但设置的异常类型不是运行时异常,则不会回滚。

1.3 同一个类中的方法调用

  • 由于@Transactional是基于AOP实现的,因此同一个类中的方法调用,不会触发事务回滚。原因是在一个事务方法内部调用另外一个有@Transactional注解的方法,Spring框架并不会再次开启一个新的事务,而是继续使用已经存在的事务。因此即使另一个方法抛出异常,也不会影响当前事务的提交或回滚。

1.4 异常被捕获的情况

  • 如果事务方法抛出一个异常,但是该异常在被当前方法所捕获,而没有被抛到事务方法之外,这时事务并不会进行回滚。这是由于Spring事务管理是通过AOP实现的,只有在方法执行时抛出异常,才会被AOP的拦截器捕获到,才能进行事务回滚。

1.5 事务回滚后的异常被捕获

  • 如果事务方法抛出一个异常导致事务回滚,但是该异常在后续代码中被捕获并处理了,而不是被抛出到上层调用方法,那么回滚不会被成功执行。在处理完异常后,后续代码会继续执行,而不是回滚到之前的状态。这时需要在异常处理中重新抛出异常,在上层调用方法中进行处理。

二、解决方案

2.1 修改默认回滚规则

  • 可以使用@Transactional注解的rollbackFor属性来指定异常回滚的类型,如@Transactional(rollbackFor = Exception.class),这样就可以把受检异常也包含进回滚的规则中,实现更加灵活的回滚控制。

2.2 手动开启新的事务

  • 可以在方法中调用自己所在的类的另一个有@Transactional注解的方法时,通过Propagation.REQUIRES_NEW参数来指定该方法必须开启新的事务,例如:

```java
@Service
public class UserServiceImpl implements UserService {

  @Autowired
  private UserMapper userMapper;

  @Override
  @Transactional
  public void updateUser(User user) {
      userMapper.updateUser(user);
      // 更新用户信息后需要往用户日志表中插入一行新纪录
      this.insertUserLog(user);
  }

  @Transactional(propagation = Propagation.REQUIRES_NEW)
  public void insertUserLog(User user) {
      UserLog userLog = new UserLog();
      userLog.setUserId(user.getUserId());
      userLog.setOperateType("update");
      userMapper.insertUserLog(userLog);
  }

}
```

2.3 解决异常被捕获的情况

  • 可以将捕获异常的代码改为抛出异常,或者通过TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()来手动设置回滚状态。例如:

java
@Override
@Transactional
public void updateUser(User user) {
try {
userMapper.updateUser(user);
throw new RuntimeException("test");
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw e;
}
}

2.4 解决事务回滚后的异常被捕获

  • 可以通过TransactionAspectSupport.currentTransactionStatus().hasRollbackOnly()方法来判断当前事务是否已经回滚,如果已经回滚,则需要重新抛出异常,例如:

java
@Override
@Transactional
public void updateUser(User user) {
try {
userMapper.updateUser(user);
throw new RuntimeException("test");
} catch (Exception e) {
if (TransactionAspectSupport.currentTransactionStatus().hasRollbackOnly()) {
throw e;
}
// ...处理异常
}
}

好了,这就是关于“spring声明式事务 @Transactional 不回滚的多种情况以及解决方案”的完整攻略。希望对你有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:spring声明式事务 @Transactional 不回滚的多种情况以及解决方案 - Python技术站

(0)
上一篇 2023年5月21日
下一篇 2023年5月21日

相关文章

  • MySQL总是差八个小时该如何解决

    关于 MySQL 总是差八个小时的问题,这个问题通常涉及到时区的问题,可以按照以下步骤进行解决。 步骤一:查看默认时区 首先,我们需要查看 MySQL 的默认时区,可以使用如下命令: SELECT @@global.time_zone, @@session.time_zone; 如果结果显示的是系统的时区,就可以跳过步骤二,直接进入步骤三。 步骤二:修改默认…

    database 2023年5月22日
    00
  • mysql中key 、primary key 、unique key 与index区别

    CREATE TABLE pre_forum_post ( pid int(10) unsigned NOT NULL COMMENT ‘帖子id’, fid mediumint(8) unsigned NOT NULL default ‘0’ COMMENT ‘论坛id’, tid mediumint(8) unsigned NOT NULL defaul…

    MySQL 2023年4月13日
    00
  • sql cast,convert,QUOTENAME,exec 函数学习记录

    让我来为您详细讲解一下“SQL CAST、CONVERT、QUOTENAME、EXEC 函数学习记录”的完整攻略。 CAST 和 CONVERT 函数 在 SQL 中,我们经常需要将一种数据类型转换为另一个数据类型,这时候我们可以使用 CAST 或 CONVERT 函数。 CAST 函数用于将一个数据类型转换为另一个数据类型,语法如下: CAST(expre…

    database 2023年5月21日
    00
  • 解决redis在linux上的部署的问题

    针对“解决redis在linux上的部署的问题”的问题,本文将提供如下方案: 一、安装redis 在linux系统上以root用户身份安装必备软件包: sudo yum update sudo yum install gcc gcc-c++ 下载redis: wget http://download.redis.io/releases/redis-5.0.1…

    database 2023年5月22日
    00
  • MySql中的存储引擎和索引

    MySQL中的存储引擎和索引是提高MySQL数据库性能的关键因素之一。以下是MySQL存储引擎和索引的完整攻略。 一、存储引擎 存储引擎是MySQL中负责数据存储和读写的底层组件。MySQL支持多种存储引擎,不同的存储引擎具有不同的特点和适用场景。下面介绍几种常见的存储引擎: 1. InnoDB InnoDB是MySQL默认的事务性存储引擎,支持事务和行锁定…

    database 2023年5月19日
    00
  • mysql8.0 my.ini 如何永久修改时区

    以下是关于“mysql8.0 my.ini 如何永久修改时区”完整攻略。 一、查看当前时区 在修改时区之前,我们需要先查看当前的时区设置。可以通过执行以下SQL语句来查看: SELECT @@global.time_zone, @@session.time_zone; 执行上述语句后,会出现两列结果,第一列时”system”,第二列为”+00:00″。这代表…

    database 2023年5月22日
    00
  • Centos 6.5下安装MySQL 5.6教程

    下面是“Centos 6.5下安装MySQL 5.6教程”的完整攻略。 准备工作 在开始安装MySQL 5.6之前,需要确保系统中已经安装了wget工具和nano编辑器。可以通过如下命令安装: yum install wget nano 下载MySQL 5.6安装包 在Centos 6.5系统上,可以通过以下命令从MySQL官方网站下载MySQL 5.6安装…

    database 2023年5月22日
    00
  • DBMS 中的外键

    DBMS 中的外键详解 什么是外键 在关系型数据库中,外键是指一个表中的某列或几列,其值依赖于另一个表的列的值。外键主要用于实现关系型数据库的数据完整性。 外键的作用 外键可以用来约束表之间的关系,确保数据的完整性。在使用外键时可以达到如下目的: 保证数据的一致性 避免出现脏数据 级联更新和删除 优化查询性能 外键的实现 外键的实现需要在数据库设计阶段对每个…

    database 2023年3月27日
    00
合作推广
合作推广
分享本页
返回顶部