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

下面我将详细讲解“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日

相关文章

  • MyBatisPlus 大数据量查询慢的问题解决

    长时间的 SQL 执行和慢查询经常是面对大量数据时的问题。在使用 MyBatisPlus 进行大数据量的查询时,也会遇到这样的问题。下面详细讲解如何解决这些问题。 问题背景 在使用 MyBatisPlus 进行大数据量的查询时,由于返回的数据较多,可能会导致 SQL 执行时间较长,甚至会出现慢查询的情况。下面列举几个可能会导致查询缓慢的因素: 数据库存储介质…

    database 2023年5月21日
    00
  • SQL 查询 SELECT

    SQL(Structured Query Language)是一种可以用来查询和处理关系型数据库的计算机语言。SELECT 是 SQL 中最常用的命令之一,它用来获取表中的数据。 下面是 SELECT 命令的语法: SELECT column1, column2, … FROM table_name; 其中,column1,column2 表示需要返回的…

    database 2023年3月27日
    00
  • DBMS 中断言和触发器的区别

    DBMS中断言和触发器都是能够在数据库中执行一些自动化操作的机制,但是它们之间有明显的区别。 断言 断言是指在应用程序和数据库之间的一种验证机制,用于确保在数据库中插入、更新或删除数据时满足某些条件。如果这些条件不被满足,就会抛出一个错误消息并回滚事务。 断言通常有两种类型:检查和动作。 检查断言验证某些数据是否已经存在于数据库中。如果它存在,插入会失败。 …

    database 2023年3月27日
    00
  • 全新Mac配置PHP开发环境教程

    首先我们需要为Mac配置PHP开发环境,这个过程大致可以分为以下几个步骤: 安装Homebrew Homebrew是Mac OS X下面非常方便的包管理器,我们可以利用它来安装PHP版本和相关的扩展等。安装Homebrew的方式有两种,一种是命令行安装,另一种是通过官网安装。 命令行安装: $ /usr/bin/ruby -e "$(curl -f…

    database 2023年5月22日
    00
  • 卸载SQL2008遇到问题(重启计算机失败、找不到SQL卸载程序)的解决办法

    以下是详细的攻略: 问题概述 在卸载SQL Server 2008时,可能会遇到以下问题: 重启计算机失败 找不到SQL卸载程序 解决方案 重启计算机失败的解决办法 手动重启计算机。 如果卸载SQL Server 2008时提示了需要重启计算机,但是重启计算机失败,可以先手动重启计算机。这样可能会解决卸载失败的问题。 禁用自动启动项。 如果手动重启计算机也失…

    database 2023年5月22日
    00
  • 详解GaussDB for MySQL性能优化

    详解GaussDB for MySQL性能优化 GaussDB for MySQL是一款企业级数据库管理系统,为了优化系统性能和减少系统运维成本,以下是一个详细的优化攻略。 1. 数据库架构 1.1 数据库设计 合理的数据模型设计可以帮助提高系统性能。 数据库的表要根据不同的用途进行分层,保证数据查询的效率。 使用正确的数据类型,避免占用过多的存储空间。 1…

    database 2023年5月19日
    00
  • Linux杀不死的进程之CPU使用率700%解决方法

    以下是关于“Linux杀不死的进程之CPU使用率700%解决方法”的完整攻略: 问题描述 有时候在Linux系统中,我们可能会遇到一些卡死的进程导致CPU使用率飙升,这些进程通常无法通过常规杀进程命令(如kill -9)来终止,这时候该怎么办呢? 解决方法 通过pstree查找父进程并杀掉 首先,我们可以通过pstree命令来查看卡死进程的父进程,然后再对父…

    database 2023年5月22日
    00
  • SQL 描述Oracle数据字典视图

    Oracle 数据字典视图是 Oracle 数据库管理的重要组成部分,它包含了 Oracle 数据库中各种对象的信息,包括表、索引、约束、序列、视图等等。使用 SQL 可以方便地查询数据字典视图,进而对数据库进行管理和优化。 以下是两个使用 SQL 查询 Oracle 数据字典视图的实例: 查询表的大小和行数 Oracle 数据字典视图中包含了表的大小和行数…

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