Spring 事务传播机制
Spring事务传播机制定义了事务方法如何与已经存在的事务进行交互,简单的理解就是多个事务方法相互调用时,事务如何在这些方法间传播。
在繁琐的业务场景中,多个事务方法间的调用可能引起事务不一致,如数据丢失、重复提交等。
在 Spring 中主要有七种事务传播级别:
- REQUIRED(默认): 如果当前存在事务,则加入该事务;如果当前没有事务,则新建一个事务。这是最常见的传播行为。
- SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务状态执行。适用于不希望事务干扰的只读操作。
- NOT_SUPPORTED: 总是以非事务状态执行操作。如果当前存在事务,则挂起当前事务。
- REQUIRES_NEW: 总是开启一个新的事务。如果当前存在事务,则挂起当前事务,并创建一个新的事务。适用于需要独立事务执行的操作。
- NESTED: 如果当前存在事务,则在嵌套事务中执行;如果当前没有事务,则行为类似于 REQUIRED。但是,嵌套事务可以独立于外部事务进行提交或回滚。
- MANDATORY: 必须在事务中执行,如果当前没有事务,则抛出异常。适用于需要强制在事务中执行的操作。
- NEVER: 总是以非事务状态执行操作。如果当前存在事务,则抛出异常。
package com.Baili.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class BailiAspect {
@Before("execution(public void com.Baili.service.UserService.test())")
public void BailiBefore(JoinPoint joinPoint) {
System.out.println("BailiBefore");
}
}
package com.Baili.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Component
public class UserService {
@Autowired
UserService userService;
@Autowired
JdbcTemplate jdbcTemplate;
@Transactional
public void test(){
jdbcTemplate.execute("INSERT INTO `test`.`employees` (`name`, `age`, `position`, `hire_time`, `remark`) VALUES ('徐庶', 20, 'shanghai', '2023-06-11 20:51:35', '测试3');\n");
userService.test2(); //代理对象调用,事务不失效,由于是NEVER级别,存在事务出现异常插入失败
test2(); //直接调用,事务失效,由于是NEVER级别,反而可以成功插入
}
@Transactional(propagation = Propagation.NEVER)
public void test2(){
jdbcTemplate.execute("INSERT INTO `test`.`employees` (`name`, `age`, `position`, `hire_time`, `remark`) VALUES ('诸葛', 20, 'shanghai', '2023-06-11 20:51:35', '测试3');\n");
}
}