原因一:自调用不走代理对象,用this.调用内层方法时注解是不生效的,例如下面的例子,u1可以插入成功,事务不生效。在控制器中的方法上加@Transactional,直接调用不生效也是这个原因。
public void test() {
try {
this.insertUser();
} catch (Exception e){
log.error("执行出错啦",e.getMessage());
}
}
@Transactional(rollbackFor = Exception.class)
void insertUser() {
User u1 = new User("Yann");
insert(u1);
int num = 5/0;
User u2 = new User("Yoki");
insert(u2);
}
将上面例子改成通过代理对象的方式调用内层方法,事务就可以生效了
public void test() {
UserService userService = (UserService) AopContext.currentProxy();
try {
userService.insertUser();
} catch (Exception e){
log.error("执行出错啦",e.getMessage());
}
}
/**
* 由于外层的方法通常也是要加事务的,所以内层的事务要
* 加上propagation = Propagation.NESTED让内层事务不会影响到外层事务
*/
@Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
void insertUser() {
User u1 = new User("Yann");
insert(u1);
int num = 5/0;
User u2 = new User("Yoki");
insert(u2);
}
原因二:@Transactional注解只能应用到public修饰符上,其它修饰符不起作用,但不报错。
原因三:默认情况下此注解会对unchecked异常进行回滚,对checked异常不回滚。如果想要对所有异常都进行回滚,注解括号中添加 “rollbackFor = Exception.class” 指定异常类型就可以了
那什么是unchecked,什么是checked呢?通俗的说,编译器能检测到的是checked,检测不到的就是unchecked。
派生于Error或者RuntimeException(比如空指针,1/0)的异常称为unchecked异常。
继承自Exception的异常统称为checked异常,如 IOException、TimeoutException等。
@Transactional(rollbackFor = Exception.class)
void insertUser() {
User u1 = new User("Yann");
insert(u1);
int num = 5/0;
User u2 = new User("Yoki");
insert(u2);
}
网友评论