Mybatis Update操做返回值問題

後端的數據持久化使用的是 Mybatis ,在作高併發下帳戶增減餘額的時候,打算使用樂觀鎖來解決這個問題。在獲取update操做的返回值時遇到了一個問題,彷佛 Mybatis 進行 update 操做獲得的 int 返回值並非影響的行數。這下就尷尬了。java

通常而言,咱們知道當咱們使用 Mybatis 在 mapper 接口中定義 insert delete 等操做,定義一個 int 類型的返回值,經過該值是否爲 0 來判斷數據庫中受影響的行數進而判斷操做是否成功。mysql

到底 update 返回值表明什麼呢?咱們來驗證一下便知道了,假設有以下一張表以及兩條數據:web

咱們來編寫一個簡單的單元測試用例來驗證下,首先使用 mybatis 簡單的寫個 mapper 進行更新操做,其中 xml 中的內容爲:sql

數據庫鏈接配置爲:數據庫

接來下,咱們來編寫一個簡單的單元測試來驗證下: update 的返回值是否是受影響的記錄的條數 ,對應的單元測試代碼以下:後端

由單元測試代碼能夠得知,咱們將要把數據庫中兩條記錄的 phone 字段的值由 12345678 修改成 66666666 ,正常狀況下, resultCode 將會返回 2 。由於 update 操做影響到數據庫中這 2 條記錄,這和咱們指望 2 是相符合的。那麼一切正常的狀況下,此次單元測試將會經過,那麼咱們運行看看結果:mybatis

單元測試經過了,再查看數據庫中的記錄:併發

這說明 mybatis 的 update 更新操做返回值的確是返回受影響的行數……真的是這樣嗎?app

咱們知道,當數據庫中的記錄被修改以後,再次執行重複的 update 操做將不會影響到新的行數,爲了驗證我說的話,咱們試試:高併發

那麼,按照這個邏輯:咱們再次執行這個單元測試應該是, resultCode 返回的應該是 0 ,和咱們的指望的數字 2 不一致,將會致使測試不經過。再次運行單元測試:

竟然仍是 passed ,看到這裏聰明的你已經看出來了, 默認狀況下,mybatis 的 update 操做返回值是記錄的 matched 的條數,並非影響的記錄條數。

嚴格意義上來將,這並非 mybatis 的返回值,mybatis 僅僅只是返回的數據庫鏈接驅動(一般是 JDBC )的返回值,也就是說,若是驅動告知更新 2 條記錄受影響,那麼咱們將獲得 mybatis 的返回值就會是 2 和 mybatis 自己是沒有關係的。

道理我都懂,若是咱們非得要 mybatis 的 update 操做明確的返回受影響的記錄條數,有沒有什麼辦法呢?

固然是有的。

經過對 JDBC URL 顯式的指定 useAffectedRows 選項,咱們將能夠獲得受影響的記錄的條數:

?
1
jdbc:mysql: //${jdbc.host}/${jdbc.db}?useAffectedRows=true

咱們對咱們的數據庫鏈接配置稍作修改,添加 useAffectedRows 字段:

此時,mybatis 的 update 操做返回的應該是受影響的條數了,咱們再次運行單元測試試試看:

update 操做返回的是受影響的記錄條數,咱們知道爲 0 和咱們預期的 2 不一致,天然而然單元測試不經過咯~。

總結

相關文章
相關標籤/搜索