成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

小心 MybatisPlus 的一個坑與面試題

開發 前端
把 saveBatch 上的 @Transactional 注解上設置事務傳播機制為:REQUIRES_NEW 或 NESTED,很明顯,我也做不到,這是 mybatis-plus 的源碼。

本文轉載自微信公眾號「 yes的練級攻略」,作者 是Yes呀。轉載本文請聯系 yes的練級攻略公眾號。

你好,我是yes。

昨天測試說有個 xx 功能用不了,扔給我一個截圖,說有報錯:

圖片

報錯信息就是:Transaction rolled back because it has been marked as rollback-only,很好理解:事務被回滾了,因為它已經被標記了只能回滾。

我一看巧了,這不就是我之前分析過的面試題嗎!

圖片

之前的文章我解釋過:這種錯一般發生在嵌套事務中,即內層事務出錯,但是由于是否提交事務的操作由外層事務觸發,于是乎內層事務只能做個標記,來設置當前事務只能回滾。

緊接著它想拋出錯誤,但是由于被 try catch 了,于是乎正常執行后續的邏輯,等執行到最后,外層要提交事務了,發現當前事務已經被打了回滾的標記,所以提交失敗,報了上面的錯。

具體原理可以看我之前的那篇文章,這里簡單舉例下會出錯的示例代碼:

大致就是下面這個代碼調用邏輯,有一個 service 標記了 @Transcational,采用默認的事務傳播機制:

圖片

緊接著 UserService#insert 調用了 addressService#errorInvoker,這個方法也標記了 @Transcational:

圖片

這樣一來,只要 addressService#errorInvoker 的調用發生報錯,那么必然能重現上面的報錯信息。

原理很清晰,我不可能犯這個錯。

我信誓旦旦的對測試說:這肯定是老陳寫的 bug,與我無關!

老陳瞄了我一眼:老子已經 2 個月沒碰過那個項目了,你扯犢子呢?

隨后這個老測試直接把更詳細的報錯扔了過來,咳咳,涉及公司的類名這里不展示的,反正確實是我的代碼....

但是我還是覺得很不可思議,這部分邏輯是我新寫的,我壓根就沒有使用嵌套事務啊!

大致的代碼如下:

@Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean xxx(xxx dto) {
        list1 = .....;
        try {
              數據庫批量保存list1;
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                //篩選過濾重復 key 的數據
                //打標發送
                數據庫批量保存過濾之后的list1;
            }
            ....
        }
        sendToMQ(xxx);
        list2 = .....;
        try {
             數據庫批量保存list2;
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                //篩選過濾重復 key 的數據
                //打標發送
                數據庫批量保存過濾之后的list2;
            }
            ...
        }
        sendToMQ(xxx);
        return Boolean.TRUE;
    }

這個接口其實是一次性接口,用來補數據的,線上跑過一次后,后面應該不會再使用。

出于保險原則,兼容上游部分數據重復調用,所以我做了重復key的處理,剔除重復的部分,讓不重復的部分正常保存。

正常情況下不會出現這個場景,剛好測試環境測試來回折騰有很多重復數據(其實我這樣寫也是為了兼容測試,隨便他折騰)

這里的代碼邏輯不復雜,明面上來看,我并沒有調用別的 service !也并不存在嵌套事務的問題,所以我思來想去也看不明白。

于是......

我出門放了個水,順帶逛了一圈,接著買了杯咖啡,遇事不決,量子力...個屁,立馬屁顛屁顛的跑回來繼續看代碼。

回來突然就看 try-catch 不爽。

但是 try 里面就是一個  mybatis-plus 的 IService,批量保存數據的操作。

難道它有什么騷操作?點進去一看突然發現:

圖片

我丟!

喚起了我的記憶,mybatis-plus 為了保證批量保存的事務性,加了 @Transactional。

合著我確實沒想著使用嵌套事務,但是這被迫上了“賊船”啊!

這本是好意,但是在我這個場景有點麻,它完美的復現了上文提到的那個錯誤使用,在有重復 key 的場景確實報錯了,但是被外層 try-catch 攔住了拋錯,不過事務上已經打了失敗的標了!

解決辦法其實很簡單:

  1. 把 saveBatch 上的 @Transactional 注解刪了,很明顯我做不到,這是 mybatisplus 的源碼。
  2. 把 saveBatch 上的 @Transactional 注解上設置事務傳播機制為:REQUIRES_NEW 或 NESTED,很明顯,我也做不到,這是 mybatis-plus 的源碼。

然后我找了下,好像也沒有什么參數可以指定 saveBatch 的事務傳播機制。

所以咋辦。。。測試還在催我,沒辦法,只能不用 mybatis-plus 的 saveBatch ,自己通過 mapper 寫個批量插入了:

圖片

一波操作提交代碼重啟服務,讓測試再試試,且輕飄飄的甩一句:這不是我的bug,我被框架坑了。

咳咳,反正我不管,我的代碼沒有bug,這是程序員最后的倔強。

最后

所以在使用三方代碼的情況下還是需要多留個心眼點點看。

我記得以前還聽說過一個段子,就是有個人用了一個網上的組件,正常情況下都沒事,異常情況下,系統就掛了。

后面一找,那個組件在個角落嘎達寫了 System.exit。

對上面這個錯誤源碼層面分析有興趣的話 ,可以看下我之前的這篇文章群里分享的面試題,第一題就不會了?

責任編輯:武曉燕 來源: yes的練級攻略
相關推薦

2021-03-16 08:56:35

Go interface面試

2011-07-18 15:08:19

SQL存儲過程

2012-08-02 09:36:58

fork面試題

2011-08-17 10:28:53

多對多查詢SQL Server

2019-08-09 09:50:38

Java編程語言面試題

2009-06-06 18:34:05

java面試題

2014-12-02 10:02:30

2020-10-28 15:07:01

Arthas

2015-07-13 09:45:32

阿里校招

2025-03-12 08:00:00

單點登錄單設備登錄程序

2024-09-26 08:03:25

2024-03-12 09:34:01

2014-09-19 11:17:48

面試題

2021-06-02 12:12:46

DevOps面試Linux

2020-06-04 14:40:40

面試題Vue前端

2023-11-13 07:37:36

JS面試題線程

2019-03-23 20:00:04

面試react.js前端

2017-08-29 14:12:16

Java面試題

2022-05-08 19:58:10

JSONPJavaScript

2011-03-24 13:27:37

SQL
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费黄色a级毛片 | 国产成人99久久亚洲综合精品 | 亚洲日本一区二区三区四区 | 成人免费一区二区三区视频网站 | 国产精品国产成人国产三级 | av黄色网| 亚洲欧美国产精品久久 | 国产一级片免费在线观看 | 欧美视频第二页 | 欧美视频在线播放 | 黄色一级毛片 | 欧美一级免费看 | 成人免费大片黄在线播放 | 欧美成人免费电影 | 日韩欧美大片 | 毛片在线看片 | 婷婷综合五月天 | www.中文字幕.com | 日韩伦理一区二区 | 久久久久久99 | 黄色成人免费看 | 粉嫩在线 | 国产午夜精品久久久 | 色永久| 欧美精品在线播放 | 99精品国产一区二区青青牛奶 | 精品一区二区三区中文字幕 | 国产精品久久久久久久午夜片 | 亚洲一一在线 | 这里只有精品999 | 免费一级黄色录像 | 欧美日韩久久精品 | 亚洲精品乱码久久久久久按摩 | 日韩高清中文字幕 | 日韩久久久久 | 欧美国产日韩在线观看 | av电影一区二区 | 亚洲美女网站 | 亚洲国产成人在线观看 | 国产91在线视频 | 久草免费电影 |