springboot+mybatis 使用事務


一、一些概念

聲明式的事務管理是基於AOP的,在springboot中可以通過@Transactional注解的方式獲得支持,這種方式的優點是:

1)非侵入式,業務邏輯不受事務管理代碼的污染。

2)方法級別的事務回滾,合理划分方法的粒度可以做到符合各種業務場景的事務管理。

本文使用目前最常用的mybatis框架來配置springboot的事務管理機制。下面進入配置方法介紹。

 

二、開啟事務 一個注解很簡單

@EnableTransactionManagement //開始事務

 

三、Service

在設計service層的時候,應該合理的抽象出方法包含的內容。

然后將方法用@Trasactional注解注釋,默認的話在拋出Exception.class異常的時候,就會觸發方法中所有數據庫操作回滾,當然這指的是增、刪、改。

當然,@Transational方法是可以帶參數的,具體的參數解釋如下:

 
屬性 類型 描述
value String 可選的限定描述符,指定使用的事務管理器
propagation enum: Propagation 可選的事務傳播行為設置
isolation enum: Isolation 可選的事務隔離級別設置
readOnly boolean 讀寫或只讀事務,默認讀寫
timeout int (in seconds granularity) 事務超時時間設置
rollbackFor Class對象數組,必須繼承自Throwable 導致事務回滾的異常類數組
rollbackForClassName 類名數組,必須繼承自Throwable 導致事務回滾的異常類名字數組
noRollbackFor Class對象數組,必須繼承自Throwable 不會導致事務回滾的異常類數組
noRollbackForClassName 類名數組,必須繼承自Throwable 不會導致事務回滾的異常類名字數組

 

代碼:

@Service
public class GeoFenceService {

    @Autowired
    private MoonlightMapper moonlightMapper;

    @Transactional(rollbackFor = Exception.class)//可以不加直接使用@Transactional
    public int addGeoFence(GeoFence geoFence) {
        String formatTime = TimeFunction.transTimeToFormatPerfect(System.currentTimeMillis());
        geoFence.setCreateTime(formatTime);
        geoFence.setUpdateTime(formatTime);
        return moonlightMapper.insertOne(geoFence);
    }

    @Transactional
    public int batchGeoFence(List<GeoFence> geoFenceList) {
        String formatTime = TimeFunction.transTimeToFormatPerfect(System.currentTimeMillis());
        for (GeoFence geoFence : geoFenceList) {
            geoFence.setCreateTime(formatTime);
            geoFence.setUpdateTime(formatTime);
        }
        return moonlightMapper.insertBatch(geoFenceList);
    }
}

四、測試一下

可以做一個簡單的測試,主動拋出異常,測試一下是否真的能保證事務性。

在執行完插入之后,手動拋出一個空指針異常,可以發現數據真的回滾了。

@Service
public class GeoFenceService {

    @Autowired
    private MoonlightMapper moonlightMapper;

    @Transactional
    public int addGeoFence(GeoFence geoFence) {
        String formatTime = TimeFunction.transTimeToFormatPerfect(System.currentTimeMillis());
        geoFence.setCreateTime(formatTime);
        geoFence.setUpdateTime(formatTime);
        int count = moonlightMapper.insertOne(geoFence);
        String a = null;
        a.indexOf('c');
        return count;
    }
}

五、如果項目啟動報錯不要急,因為我也遇到了,下面解決一下

報錯信息:

使用spring-boot做事務管理時,出現異常:The bean 'xxx' could not be injected as a 'xx.xxxx' because it is a JDK dynamic proxy that implements:

搞了半天發現是因為代理的原因;

異常信息:

 

 

解決方案:

因為加了@Transaction的類會自動開啟動態代理,java的代理機制主要有JDK動態代理和CGLIB,報上面的錯誤是因為使用了JDK動態代理機制,我嘗試開啟@Transaction設置@EnableTransactionManagement(proxyTargetClass = true),問題解決;特此記錄一下;

 


免責聲明!

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



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