实验步骤
我主要实验了3种情况..这三种情况我觉得是最容易弄错的...其他的Propagation还是比较好理解的...
具体实验步骤是我写了2个嵌套的Service.外侧的Service用的是Propagation.REQUIRED.内侧的Service分别试了Propagation.REQUIRED, Propagation.REQUIRES_NEW 和 Propagation.NESTED
请注意外层Service在调用内层Service的时候用了trycatch..不然内层抛出异常外层不处理的话也会抛出异常.
我的Service看起来是这样的:
@Transactional(propagation = Propagation.REQUIRED)
public void operate1() {
House s = new House();
s.setName("841o1");
repository.save(s);
try{
service.operate2();
}catch (Exception e) {
e.printStackTrace();
}
House s3 = new House();
s3.setName("843o1");
repository.save(s3);
throw new RuntimeException();
}
@Transactional(propagation = Propagation.NESTED)
public void operate2() {
House s = new House();
s.setName("842o2");
repository.save(s);
//throw new RuntimeException();
}
流程就是外侧Service保存对象1,内侧Service保存对象2,外侧Service保存对象3
实验结果
外层Service抛出异常 | 内层Service抛出异常 | |
内层Service是Propagation.REQUIRED | 对象1,2,3全部回滚 | 对象1,2,3全部回滚 |
内层Service是Propagation.REQUIRES_NEW | 对象1,3回滚,2成功提交 | 对象1,3提交成功,2回滚 |
内层Service是Propagation.NESTED | 对象1,2,3全部回滚 | 对象1,3提交成功,2回滚 |
结论
Propagation.REQUIRED : 内外层事务可以看成是同一个事务,一起commit,或者一起rollback.
Propagation.REQUIRES_NEW : 内外层事务完全不相关, 就是2个事务
Propagation.NESTED : 外层事务commit内层事务才可能commit,外层事务rollback内层事务一定rollback..外层事务commit,内层事务仍然可能会rollback
另外:
我用Spring data jpa实验Propagation.NESTED的时候提示我jpa的实现(hibernate)不支持savepoint.
我直接用hibernate的时候就可以,但是要设置org.springframework.orm.hibernate4.HibernateTransactionManager的nestedTransactionAllowed属性为true