事务回滚分析 @Transaction rollbackfor
1.@Transactional的rollbackfor默认回滚异常
不设置rollbackfor时,默认遇到运行时异常(RuntimeException)才回滚事务,非运行时异常不会回滚
2.只有@Transactional,运行时异常和非运行时异常回滚测试
情景1:运行时异常(异常抛出) java.lang.ArithmeticException: / by zero
@Transactional
public void test1(){
userMapper.insert("LiLei",122);
System.err.println(1/0);
}
运行结果: 事务回滚 org.springframework.transaction.interceptor.TransactionInterceptor.invoke ,数据没有插入到数据库
情景2:运行时异常(异常捕获) java.lang.ArithmeticException: / by zero
@Transactional public void test1(){ userMapper.insert("LiLei1",122); try { System.err.println(1/0); } catch (Exception e) { e.printStackTrace(); } }
运行结果:事务未回滚,数据成功插入到数据库
情景3:运行时异常(异常捕获再抛出)
@Transactional public void test1(){ userMapper.insert("LiLei11",122); try { System.err.println(1/0); } catch (ArithmeticException e) { e.printStackTrace(); throw e; } }
运行结果: 事务回滚,数据没有插入到数据库
情景4:非运行时异常(异常抛出) java.lang.ClassNotFoundException: null
@Transactional
public void test1() throws ClassNotFoundException {
userMapper.insert("LiLei",122);
throw new ClassNotFoundException();
}
运行结果:事务未回滚,数据成功插入到数据库
情景5:非运行时异常(异常捕获) java.lang.ClassNotFoundException: null
@Transactional public void test1() { userMapper.insert("LiLi",122); try { throw new ClassNotFoundException(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
运行结果:事务未回滚,数据成功插入到数据库
小结:
@Transactional 未设置 rollbackfor 时,默认识别运行时异常 RunTimeException() ,非运行时异常不会回滚,且RunTimeException()被捕获时不会触发事务回滚.
我们比较熟悉的RumtimeException类的子类有
Java.lang.ArithmeticException
Java.lang.ArrayStoreExcetpion
Java.lang.ClassCastException
Java.lang.IndexOutOfBoundsException
Java.lang.NullPointerException
3.指定rollbackfor=Exception.class回滚测试
情景1:
@Transactional(rollbackFor = Exception.class)
public void test1(){
userAdd2("Jobs",22);
}
public void userAdd2(String name,Integer age){
userMapper.insert(name,age);
try {
throw new NullPointerException();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
运行结果:事务未回滚,数据成功录入
情景2:
@Transactional(rollbackFor = Exception.class)
public void test1(){
userAdd2("Jobs",22);
}
public void userAdd2(String name,Integer age){
userMapper.insert(name,age);
throw new NullPointerException();
}
运行结果:事务回滚,数据没有插入到数据库
小结:
这两个情景的测试结果很明显了,由步骤2的5个情景已经可以推测出结果
4.@Transactional()的回滚失效分析
情况1:上边提到的异常被捕获处理,且 外层方法添加了事务
情况2:外层方法没添加事务
public void test1(){
userAdd1("Jobs",22);
}
@Transactional
public void userAdd1(String name,Integer age) {
userMapper.insert(name,age);
System.err.println(1/0);
}
运行结果:事务未回滚,数据成功插入到数据库
原因分析:
AOP 使用的是动态代理的机制,它会给类生成一个代理类,事务的相关操作都在代理类上完成。内部方式使用this
调用方式时,使用的是实例调用,并没有通过代理类调用方法,所以会导致事务失效