概括
@Transactional注解有两个,一个是spring提供的@org.springframework.transaction.annotation.Transactional
另一个是jdk提供@javax.transaction.Transactional
。在回滚的设置上,spring提供的是rollbackFor
,jdk提供的是rollbackOn
,在使用方法上是一致的。
这两个注解在我有限的测试里表现是一样的。
用在哪里
@Transactional
注解既可以写在方法上也可以写在类上。写在类上则这个类的所有public方法都将会有事务。这样显然会使一些不需要事务的方法产生事务,所以更好的做法是在想要添加事务的方法上标注@Transactional
。
rollbackFor
@Transactional
的rollbackFor用于指定能够触发事务回滚的异常类型,可以指定多个,用逗号分隔。
rollbackFor
默认值为UncheckedException,包括了RuntimeException和Error.
当我们直接使用@Transactional
不指定rollbackFor
时,Exception及其子类都不会触发回滚。
public class BusinessException extends Exception {
public BusinessException(String msg) {
super(msg);
}
}
@Autowired
private UserRepository userRepository;
// 不回滚
@Transactional
public void test1() throws Exception {
User user = new User(1, "15000000000", "d243ewa", "Comma");
saveUser(user);
throw new Exception("test1 error");
}
// 不回滚
@Transactional
public void test11() throws Exception {
User user = new User(1, "15000000000", "d243ewa", "Comma");
saveUser(user);
throw new BusinessException("test11 error");
}
// 回滚
@Transactional(rollbackOn = Exception.class)
public void test2() throws Exception {
User user = new User(1, "15000000000", "d243ewa", "Comma");
saveUser(user);
throw new Exception("test2 error");
}
// 回滚
@Transactional(rollbackOn = Exception.class)
public void test21() throws Exception {
User user = new User(1, "15000000000", "d243ewa", "Comma");
saveUser(user);
throw new BusinessException("test21 error");
}
// 回滚
@Transactional
public void test3() {
User user = new User(1, "15000000000", "d243ewa", "Comma");
saveUser(user);
throw new RuntimeException("test3 runtime error");
}
// 不回滚
@Transactional
public void test4() throws Exception {
User user = new User(1, "15000000000", "d243ewa", "Comma");
test41(user);
throw new Exception("test4 error");
}
@Transactional(rollbackOn = Exception.class)
public void test41(User user) {
saveUser(user);
}
// 不回滚
public void test5() throws BusinessException {
test6();
}
// 回滚
@Transactional(rollbackOn = Exception.class)
public void test6() throws BusinessException {
User user = new User(1, "15000000000", "d243ewa", "Comma");
saveUser(user);
throw new BusinessException("test6 error");
}
// 回滚
@Transactional(rollbackOn = Exception.class)
public void test7() throws BusinessException {
test8();
}
public void test8() throws BusinessException {
User user = new User(1, "15000000000", "d243ewa", "Comma");
saveUser(user);
throw new BusinessException("test8 error");
}
public User saveUser(User user) {
return userRepository.save(user);
}
- 有一点需要注意,在service中间接调用的方法不会触发事务,具体可以看下这篇文章https://zhuanlan.zhihu.com/p/38208248 ,感谢作者的详细讲述。
网友评论