数据库自增id在这时候会跳跃,因为一个事务占了两个id,有一个会退掉了。
事务的传播级别是指当前的事务对于外层事务的关系。
1.REQUIRED
内外为同一个事务,且内层抛出异常后,内层先回滚并把事务设置为rollback-only,外层是在commit时候发现是rollback-only的,所以回滚并抛出UnexpectedRollbackException异常;
外层异常后,会把内外的操作同时回滚。
@Service
public class Inner {
@Autowired
AffiarMapper affiarMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void test() {
Affiar affiar = new Affiar();
affiar.setName("hyq1");
affiarMapper.insert(affiar);
throw new RuntimeException("inner ex");
}
}
@Service
public class Outter {
@Autowired
Inner inner;
@Autowired
AffiarMapper affiarMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void test() {
Affiar affiar = new Affiar();
affiar.setName("hyq");
affiarMapper.insert(affiar);
try {
inner.test();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
2.REQUIRES_NEW
声明 REQUIRES_NEW 的话就会创建一个新的物理事务,内层事务的提交回滚都是独立于外层事务的。外层事务不受内层事务结果的影响,他们运行于独立的物理事务。
外层的回滚也不影响内层的操作。
如果两个事务有锁竞争会形成死锁,比如内外层都要更新同一条记录,因为外层的事务要等内部的事务结束一起提交,但是内部的事务又要等外部的事务释放锁(REQUIRED不会,因为他们是一个事务)。
3. NESTED
NESTED 使嵌套的事务使用相同的物理事务,但是对嵌套调用设置了保存点,所以 inner 事务可以独立于 outer 事务回滚。
如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。
4. SUPPORTS
支持事务,如果当前存在事务,就沿用当前事务,如果不存在,则继续采用无事务的方式运行。
5. MANDATORY
必须使用事务。如果当前没有事务,则会抛出异常,如果存在当前事务,就沿用当前事务。(如果不存在事务,抛出异常不影响外部逻辑)
6. NOT_SUPPORTED
不支持事务,当前存在事务时,将挂起事务(外层挂起),运行当前方法(内层方法)。
7. NEVER
不支持事务,如果当前方法存在事务,则抛出异常-Existing transaction found for transaction marked with propagation ‘never’,否则继续使用无事务机制运行。