mybatis 有時update語句執行無效的解決方案
項目裡mybatis有時update語句執行無效
公司測試人員在測試的時候發現,在積分系統,消費產生瞭積分,有時候,卻不能加到用戶累計積分上去。
明明積分流水記錄跟用戶積分的增加在一個事務當中的。積分流水記錄生成成功,偏偏用戶積分沒有加上去?奇瞭怪瞭。
加積分的代碼是:
tMemberPointMapper.updateByPrimaryKeySelective(tMemberPoint);
然後在相應的位置,加瞭日志,記錄更新語句前後的對比。
測試人員再次發現問題時查看瞭日志,日志顯示更新語句執行後的對象確實是有累加過積分的。為什麼數據庫表中的值就是沒變呢?
於是百度啊,這種情況百度的結果比較少,有的說是mybatis的版本的問題?個人感覺不太可能,因為這個mybatis版本在很多項目是使用,都沒出過問題。事務也是測試過,有異常能夠回滾。
後來冷靜下來想瞭想出現問題的時機。測試人員在消費操作過後,會立刻點查看用戶積分的界面。這時會調獲取用戶積分信息的接口。因為這個接口,不僅僅是查詢,因為等級維持機制(過一定的周期,要扣掉一部分積分), 它在查詢前,對用戶積分有修改的操作。所在,查詢用戶積分的接口,也處在非隻讀的事務中。
當兩個對同條用戶積分記錄操作的事務同時執務(InnoDb的行級鎖,排它鎖),由於,mysql的默認隔離級別是repeatable-read,事務A和事務B,讀到數據為a,後事務B修改瞭數據為b,提交瞭,而事務A再執行修改操作,又會把數據b修改為數據a。這就出現瞭,題中所述的,偶爾出現update語句執行無效的假象。
解決辦法
悲觀鎖 在查詢語句後加 for update ,鎖住事務中,查詢用戶積分的語句。
<select id="selectByExample" resultMap="BaseResultMap" parameterType="com.ice.pojo.f3.TMemberPointExample" > select <if test="distinct" > distinct </if> <include refid="Base_Column_List" /> from t_member_point <if test="_parameter != null" > <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null" > order by ${orderByClause} </if> for update </select>
執行update語句後,數據沒有被更新,也沒有報錯
記錄一下今天遇到的一個問題:
問題描述
執行update語句後,數據沒有被更新,也沒有報錯
詳細情況
通過傳參的方式,在控制臺打印出的sql語句;將sql語句拷貝到數據庫執行也是OK
解決辦法
百思不得其解,到底問題出在瞭那裡?
所以,試瞭很多方法,最後才發現某一個字段的問題;但是從控制臺打印的sql語句來看,參數值也是OK的啊;
然後我嘗試將mapper中sql語句的參數寫成控制臺打印出來的參數,直接確定下來,運行,發現也是OK的,那麼確定是這個參數問題瞭;
但是映射啥的都沒問題,所以問題就有可能在數據庫存的這個字段的長度問題瞭,最後發現數據庫該字段的長度長於傳的參數的值,而且在實體類中使用trim()對屬性值做瞭處理,所以問題就在這裡,修改一下就好瞭。
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- mybatis中mapper.xml文件的常用屬性及標簽講解
- myBatis的mapper映射文件之批量處理方式
- 解決mybatis update並非所有字段需要更新問題
- mybatis中映射文件include標簽的應用
- MyBatis中關於SQL的寫法總結