1. 程式人生 > >springBoot service 事務註解@Transactional不起作用的解決

springBoot service 事務註解@Transactional不起作用的解決

在springBoot使用事物時,發現事務並沒有正常執行,沒有進行回滾

    @Transactional
    public void add(String companyName,String name) throws MyException{
	   companyDao.add(companyName);
        try {
	   userDao.addUser(name);
        }catch (DuplicateKeyException e){//這裡在資料庫將name設定成unique key
            logger.error("新增失敗。姓名:[ {} ],已存在",name);
            throw new MyException("新增失敗,名字已存在");//自定義異常  繼承Exception
        }
    }



上述姓名重複時發現,公司名稱依然新增成功,並沒有進行回滾操作。

分析:預設spring事務只在發生未被捕獲的 RuntimeException 時才回滾。  
spring aop  異常捕獲原理:被攔截的方法需顯式丟擲異常,並不能經任何處理,這樣aop代理才能捕獲到方法的異常,才能進行回滾,預設情況下aop只捕獲 RuntimeException 的異常,但可以通過配置來捕獲特定的異常並回滾  
換句話說在service的方法中不使用try catch 或者在catch中最後加上throw new runtimeexcetpion(),這樣程式異常時才能被aop捕獲進而回滾
解決辦法:

1.首先確認資料庫支援事務。即為InnoDB。

方案一:手動回滾。給註解加上引數如:@Transactional(rollbackFor=Exception.class)

方案二:如上述分析。MyException改為繼承RuntimeException的異常。並且在service上層要繼續捕獲這個異常並處理
方案三:在service層方法的catch語句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();語句,手動回滾,這樣上層就無需去處理異常