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代理))。对于非公共方法,代理对象无法直接调用,因为它们在外部不可见。 ↩︎
相关推荐
没有bug.的程序员5 小时前
Spring Cloud Gateway 性能优化与限流设计
java·spring boot·spring·nacos·性能优化·gateway·springcloud
小坏讲微服务10 小时前
SpringCloud零基础学全栈,实战企业级项目完整使用
后端·spring·spring cloud
专注VB编程开发20年12 小时前
C#VB.NET中实现可靠的文件监控(新建、删除、改名、内容修改等事件的准确捕获)
spring·c#·.net·文件监控
原来是好奇心14 小时前
Spring Boot缓存实战:@Cacheable注解详解与性能优化
java·spring·mybatis·springboot
神仙别闹18 小时前
基于SpringMVC+Spring+MyBatis开发的个人博客网站
java·spring·mybatis
q***062919 小时前
Spring Boot + Spring AI快速体验
人工智能·spring boot·spring
后端小张19 小时前
【JAVA 进阶】Spring Boot 注解体系与工程实践
java·开发语言·spring boot·后端·spring·spring cloud·java-ee
考虑考虑20 小时前
springboot中yml、yaml、properties加载顺序
spring boot·后端·spring
凌波粒1 天前
SpringMVC基础教程(1)--MVC/DispathcerServlet
java·spring·mvc
武子康1 天前
Java-173 Neo4j + Spring Boot 实战:从 Driver 到 Repository 的整合与踩坑
java·数据库·spring boot·后端·spring·nosql·neo4j