springboot事務中的一些坑


springboot開啟聲明式事務方式

  • 在Application啟動類中加入注解@EnableTransactionManagement(mode = AdviceMode.PROXY)
  • 在需要加入事務的方法上加入注解@Transactional
  • @Transactional(rollbackFor = RollbackException.class) 拋出指定異常時回滾
    /**
     * <p>
     *      (rollbackFor = RollbackException.class) 拋出自定義異常時,回滾事務。
     * </p>
     * @throws RollbackException
     */
    @Override
    @Transactional(rollbackFor = RollbackException.class)
    public void insertThenRollback() throws RollbackException {
        jdbcTemplate.execute("INSERT INTO Student (NAME) VALUES ('Tom')");
        throw new RollbackException();
    }

常見問題

例如有這個實現類StudentServiceImpl:

@Component
public class StudentServiceImpl implements StudentService {

    /**
     * <p>
     *      (rollbackFor = RollbackException.class) 拋出自定義異常時,回滾事務。
     * </p>
     * @throws RollbackException
     */
    @Override
    @Transactional(rollbackFor = RollbackException.class)
    public void insertThenRollback() throws RollbackException {
        jdbcTemplate.execute("INSERT INTO Student (NAME) VALUES ('BBB')");
        throw new RollbackException();
    }
    
        /**
     * <p>
     *      spring的事務是通過aop進行代理增強的。
     *      這里是在類的內部直接執行方法調用,並沒有調用代理類來進行方法調用,所以這里事務不會回滾。
     * </p>
     *
     * @throws RollbackException
     */
    @Override
    public void invokeInsertThenRollback1() throws RollbackException {
        insertThenRollback();
    }
    
}

上面的insertThenRollback()回回滾事務,invokeInsertThenRollback1()調用了insertThenRollback()方法但是不會回滾事務,這是為什么呢?
這是因為spring的事務是通過aop進行代理增強的,但這里是在類的內部直接執行方法調用,並沒有調用代理類來進行方法調用,所以這里事務不會回滾。

解決辦法

  • 第一種方法:通過AopContext.currentProxy()獲取當前類的代理對象。
    /**
     *
     * 通過AopContext.currentProxy()獲取當前類的代理對象
     *
     * @throws RollbackException
     */
    @Override
    public void invokeInsertThenRollback2() throws RollbackException {
        ((StudentService) (AopContext.currentProxy())).insertThenRollback();
    }
  • 第二種方法:把自己的實例注入進來,讓spring為我們創建代理。
    //把自己的實例注入進來
    @Autowired
    private StudentService studentService;
    
    
    /**
     * 把自己的實例注入進來
     * @throws RollbackException
     */
    @Override
    public void invokeInsertThenRollback3() throws RollbackException {
        studentService.insertThenRollback();
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM