spring的@Transactional注解在调用关系中失效的探索
背景
@Transactional 用于将多次使用sql对数据库进行操作的方法定义为一个原子操作(自己的理解,定义出来的。原子操作指将整个或者多个操作视作一个整体,若操作全部成功则成功执行,若有一个操作出现失败则全部操作进行回滚,放弃本次进行的所有操作),但是@Transactional 注解在方法调用的时候,在特殊情况下会出现失效的情况,故作此探究。
过程
同一个类中a方法带有@Transactional 注解,b方法不带注解。在b方法中调用a方法。
@Autowired
IBandDao bandDao;
@Transactional
public void insert() {
bandDao.insert(new Band(4, "test5", "test5", Byte.parseByte("9")));
int i = 1 / 0;
}
public void save() {
insert();
}
执行以下测试:
@Test
public void test() {
dao.save();
}
结果:
数据被成功插入,@Transactional 注解失效。
在数据库删除这条数据,进行新的测试,下同。
同一个类中a方法不带注解,b方法带@Transactional 注解。在b方法中调用a方法。
@Autowired
IBandDao bandDao;
public void insert() {
bandDao.insert(new Band(4, "test5", "test5", Byte.parseByte("9")));
int i = 1 / 0;
}
@Transactional
public void save() {
insert();
}
结果:
数据未被插入,@Transactional 注解生效。
同一个类中a方法不带注解,b方法带@Transactional 注解。在b方法中调用a方法。
结论
在同一个类中,未使用注解的方法调用使用@Transactional 注解的方法将导致@Transactional 失效
拓展
事物传播行为介绍:
@Transactional(propagation=Propagation.REQUIRED) :如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
@Transactional(propagation=Propagation.NOT_SUPPORTED) :容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW) :不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY) :必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER) :必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS) :如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
备注:
Propagation.REQUIRES_NEW 起一个新的事务,如果新的事务发生异常,不会影响旧的事务