浅谈Spring中的事务回滚
1.代码中事务控制的3种方式
② 注解事务,直接在注解上面指定,代码如下
@Transactional(rollbackFor=Exception.class)
- 编程式事务:就是直接在代码里手动开启事务,手动提交,手动回滚。优点就是可以灵活控制,缺点就是太麻烦了,太多重复的代码了。
- 声明式事务:就是使用SpringAop配置事务,这种方式大大的简化了编码。需要注意的是切入点表达式一定要写正确。
- 注解事务:直接在Service层的方法上面加上@Transactional注解,个人比较喜欢用这种方式。
- (1)声明式事务配置切入点表达式写错了,没切中Service中的方法
- (2)Service方法中,把异常给try catch了,但catch里面只是打印了异常信息,没有手动抛出RuntimeException异常
- (3)Service方法中,抛出的异常不属于运行时异常(如IO异常),因为Spring默认情况下是捕获到运行时异常就回滚
- (1)如果采用编程式事务,一定要确保切入点表达式书写正确
- (2)如果Service层会抛出不属于运行时异常也要能回滚,那么可以将Spring默认的回滚时的异常修改为Exception,这样就可以保证碰到什么异常都可以回滚。具体的设置方式也说下:
- (3)只有非只读事务才能回滚的,只读事务是不会回滚的
- (4)如果在Service层用了try catch,在catch里面再抛出一个 RuntimeException异常,这样出了异常才会回滚
- (5)如果你不喜欢(4)的方式,你还可以直接在catch后面写一句回滚代码(TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); )来实现回滚,这样的话,就可以在抛异常后也能return 返回值;比较适合需要拿到Service层的返回值的场景。具体的用法可以参见考下面的伪代码
- /** TransactionAspectSupport手动回滚事务:*/
- @Transactional(rollbackFor = { Exception.class })
- public boolean test() {
- try {
- doDbSomeThing();
- } catch (Exception e) {
- e.printStackTrace();
- //就是这一句了, 加上之后抛了异常就能回滚(有这句代码就不需要再手动抛出运行时异常了)
- TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
- return false;
- }
- return true;
- }