case 1:抽象方法上的事务注解是否会生效?
@Component
public abstract class BaseService {
@Autowired
protected JdbcTemplate jdbcTemplate;
@Transactional(rollbackFor = Exception.class, isolation = Isolation.REPEATABLE_READ)
public abstract void abstractInsert();
}
@Component
public class BaseServiceImpl extends BaseService {
@Override
// @Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
public void abstractInsert() {
System.out.println(IsolationUtils.getCurrentIsolation());
jdbcTemplate.execute("INSERT INTO `local_db`.`t_sys_user` (id) VALUES(NULL);");
}
}
打印结果:打印 REPEATABLE_READ
,说明会生效。
case 2:父子事务方法都有事务注解,采用谁的?
@Component
public class BaseServiceImpl extends BaseService {
@Override
@Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
public void abstractInsert() {
System.out.println(IsolationUtils.getCurrentIsolation());
jdbcTemplate.execute("INSERT INTO `local_db`.`t_sys_user` (id) VALUES(NULL);");
}
}
放开子方法上的事务注释,打印:SERIALIZABLE
,说明就近使用子的。
case 3:父子事务方法互相调用时,使用谁的事务注解中的规则?
@Component
public abstract class BaseService {
@Autowired
protected JdbcTemplate jdbcTemplate;
@Transactional(rollbackFor = Exception.class)
public void overrideAbstractInsert() {
TransactionSynchronizationManager.setCurrentTransactionName("Parent overrideAbstractInsert");
jdbcTemplate.execute("INSERT INTO `local_db`.`t_sys_user` (name) VALUES('parent trx');");
((BaseService) AopContext.currentProxy()).doOverrideAbstractInsert();
int i = 1 / 0;
}
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public abstract void doOverrideAbstractInsert();
}
@Component
public class BaseServiceImpl extends BaseService {
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
@Override
public void doOverrideAbstractInsert() {
System.out.println(TransactionSynchronizationManager.getCurrentTransactionName());
jdbcTemplate.execute("INSERT INTO `local_db`.`t_sys_user` (name) VALUES('child trx');");
}
}
结论:
- 需要根据事务方法入口是谁而定。
- 当起始的事务方法内部再次调用其他的事务方法,事务规则是否生效,取决于是否使用事务代理对象调用的事务方法。
- 若内部调用的事务方法是一个抽象方法,事务注解的应用规则与 case 2 相同。
证明子事务方法使用的事务注解为子类重写方法上的事务注解:
- 子事务方法中输出的事务名称为:
org.xxx.BaseServiceImpl.doOverrideAbstractInsert
,说明使用的子事务 > 说明事务传播行为使用的Propagation.REQUIRES_NEW
> 说明没有使用抽象方法上的Propagation.REQUIRED
- 子事务方法中数据插入成功:虽然父事务抛出了异常,但没有影响子事务的数据添加 > 说明使用的是
Propagation.REQUIRES_NEW
> 说明没有使用抽象方法上的Propagation.REQUIRED