@Transactional作用
主要用于声明式事务管理。它可以用于类或者方法级别,控制方法中的数据库操作是否要被事务管理。当 @Transactional 注解应用于某个方法时,该方法中的所有数据库操作(增、删、改等)会被绑定到一个事务中,保证这些操作在一个整体的事务上下文中执行。
@Transactional属性
propagation属性 - 事务传播范围
propagation 代表事务的传播行为,默认值为 Propagation.REQUIRED
- Propagation.REQUIRED:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。( 也就是说如果A方法和B方法都添加了注解,在默认传播模式下,A方法内部调用B方法,会把两个方法的事务合并为一个事务 )
- Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。
- Propagation.MANDATORY:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。
- Propagation.REQUIRES_NEW:重新创建一个新的事务,如果当前存在事务,暂停当前的事务。( 当类A中的 a 方法用默认Propagation.REQUIRED模式,类B中的 b方法加上采用 Propagation.REQUIRES_NEW模式,然后在 a 方法中调用 b方法操作数据库,然而 a方法抛出异常后,b方法并没有进行回滚,因为Propagation.REQUIRES_NEW会暂停 a方法的事务 )
- Propagation.NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务,暂停当前的事务。
- Propagation.NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常。
- Propagation.NESTED :和 Propagation.REQUIRED 效果一样。
isolation 属性 - 事务隔离级别
isolation :事务的隔离级别,默认值为Isolation.DEFAULT
- Isolation.DEFAULT:使用底层数据库默认的隔离级别。
- Isolation.READ_UNCOMMITTED:读未提交
- Isolation.READ_COMMITTED:读已提交
- Isolation.REPEATABLE_READ:可重复读
- Isolation.SERIALIZABLE:串行化
timeout 属性 - 事务超时时间
事务的超时时间,默认值为 -1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
readOnly 属性
指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
rollbackFor 属性 - 指定异常触发事务回滚
用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。
noRollbackFor属性 - 指定异常不触发事务回滚
抛出指定的异常类型,不回滚事务,也可以指定多个异常类型。
示例
@RequestMapping("/test")
@RestController
public class TestController {
@Autowired
private TestService testService;
@PostMapping("/doTransactionTest")
public String doTransactionTest(@RequestBody RolePO rolePO) {
return testService.doTransactionTest(rolePO);
}
}
@Service
public class TestService {
@Resource
private RolePOMapper rolePOMapper;
@Transactional(rollbackFor=RuntimeException.class)
public String doTransactionTest(RolePO rolePO) {
rolePO.setId(UUID.randomUUID().toString().replace("-", ""));
rolePO.setCode(1);
rolePO.setCreateTime(new Date());
rolePO.setStatus(true);
int count = rolePOMapper.insert(rolePO);
if (count > 0) {
throw new RuntimeException("异常错误");
}
return "count = " + count;
}
}
@Transactional失效场景
方法内部调用@Transactional修饰的方法事务不生效
@Transactional事务场景也是基于动态代理实现的,那么相当于给方法增强,通过代理对象处理,而通过this调用的是源对象,绕过了代理对象,所以事务不生效。
@Service
public class TestService {
@Resource
private RolePOMapper rolePOMapper;
public String doTransactionTest(RolePO rolePO) {
int count = this.doInnerTest(rolePO);
return "count = " + count;
}
@Transactional(rollbackFor=RuntimeException.class)
public int doInnerTest(RolePO rolePO) {
rolePO.setId(UUID.randomUUID().toString().replace("-", ""));
rolePO.setCode(1);
rolePO.setCreateTime(new Date());
rolePO.setStatus(true);
int count = rolePOMapper.insert(rolePO);
if (count > 0) {
throw new RuntimeException("异常错误");
}
return count;
}
}