Spring的事务管理机制

Spring的事务管理机制

事务是一组操作的集合,是一个不可分割的操作。事务会将所有的操作视为一个整体向系统提交或撤销操作请求,这一组操作集合要么全部成功,妖媚全部失败。

Spring声明式事务@Transactional

Spring中也为事务提供了支持,通过@Transactional注解在方法执行前自动开启事务,方法执行完毕之后自动提交事务。如果这个方法在执行过程中出现异常就会自动进行事务的回滚。

@Transactional

  • 可以用来修饰方法或类。@Transactional注解默认只对public方法生效,这是由于Spring的事务管理是基于动态代理[1](#1)现的

为了更好的观察Spring事务管理相关信息,我们可以在application.yml配置文件中开启事务管理日志,观察其日志信息。

yaml 复制代码
#spring 事务管理日志
logging:
  level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug

访问对应接口,如下:

java 复制代码
@Service
@Slf4j
public class UserServiceImpl implements UserService {


    @Autowired
    private UserMapper userMapper;

    @Transactional //开启Spring的事务管理
    @Override
    public void save(User user) {
        log.info("[UserService#save]: 开始执行");
        userMapper.insert(user);
        log.info("[UserService#save]: 结束执行");
    }
}

观察控制台输出日志,如下:

  • 程序正常运行结束

观察数据库,数据正确插入:

  • 程序异常结束

观察数据库,数据回滚没有保存到数据库中:

@Transactional常见的三个属性

  1. rollbackFor:异常回滚属性,指定能够出发事务回滚的异常类型。

  2. isolation:控制事务的隔离级别,默认隔离级别为Isolation.DEFAULT

  3. propagation:事务的传播机制,默认传播行为为Propagation.REQUIRED

rollbackFor

我们知道通过@Transactional注解进行事务管理时,当该方法发生异常时会执行rollback回滚操作,那么是不是什么类型的异常都会执行rollback操作呢?

如果不进行显示指定,默认情况下只有出现RuntimeException及其子类和Error及其子类才会回滚事务。

java 复制代码
//如果还需要指定对特定异常的回滚,可以通过rollbackFor属性进行指定
@Transactional(rollbackFor = [...])

isolation

SQL标准定义了四种隔离级别:

隔离级别 解释
READ UNCOMMITTED 读未提交,该隔离级别可以看到其他事务中未提交的数据(脏读问题
READ COMMITTED 读已提交,该隔离级别可以看到其他事务中已提交的数据(由于事务的执行中可能有多个事务提交,所以可能出现不可重复读问题
REPEATABLE READ 可重复读,该隔离级别可能出现幻读问题
SERIALIZABLE 串行化

在Spring事务中提供了五种隔离级别来支持sql标准的隔离级别:

spring提供的事务隔离级别 解释
Isolation.DEFAULT 以连接的数据库的事务隔离级别为主
Isolation.READ_UNCOMMITTED 读未提交
Isolation.READ_COMMITTED 读已提交
Isolation.REPEATABLE_READ 可重复读
Isolation.SERIALIZABLE 串行化

我们可以通过isolation属性进行设置

java 复制代码
@Transactional(isolation = ...)

propagation

通过这个属性我们可以配置事务的传播行为,即当一个事务方法被另一个调用时,这个事务方法如何进行事务控制。

常见的事务传播行为:

属性值 含义
Propagation.REQUIRED 默认的事务传播级别,需要事务,有则加入,无则创建新事务
Propagation.REQUIRES_NEW 需要新事务,无论有无,总是创建新事务
Propagation.SUPPORTS 支持事务,有则加入,无则在无事务状态中运行
Propagation.NOT_SUPPORTED 不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务
Propagation.MANDATORY 必须有事务,否则抛异常
Propagation.NEVER 必须没事务,否则抛异常
Propagation.NESTED 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行。如果当前无事务,则创建新事物

  1. 动态代理是通过创建代理对象来拦截对目标对象的方法调用。代理对象只能调用目标对象的公共方法(因为代理对象通常是一个新生成的类,它要么实现了和目标对象相同的接口(JDK动态代理),要么是目标对象的子类(CGLIB代理))。对于非公共方法,代理对象无法直接调用,因为它们在外部不可见。 ↩︎
相关推荐
!chen3 小时前
如何在新的Spring Boot项目中关闭Spring Security?
java·spring·jar
珹洺7 小时前
Java-Spring入门指南(十九)thymeleaf基本概念
java·spring·状态模式
whltaoin7 小时前
AI 超级智能体全栈项目阶段四:学术分析 AI 项目 RAG 落地指南:基于 Spring AI 的本地与阿里云知识库实践
人工智能·spring·阿里云·向量数据库·rag
PH = 720 小时前
Spring Ai Alibaba开发指南
java·后端·spring
涛声依旧21 小时前
基于springBoot鲜花商城小程序
java·spring·微信小程序
magicalmuggle1 天前
Java 后端开发复习指南
java·spring
Elieal1 天前
SpringMVC 进阶:核心组件详解与参数绑定全攻略
spring·maven
z晨晨1 天前
Java求职面试实战:从Spring到微服务的全面挑战
java·数据库·spring·微服务·面试·技术栈
麦兜*1 天前
Redis多租户资源隔离方案:基于ACL的权限控制与管理
java·javascript·spring boot·redis·python·spring·缓存