MyBatis-Plus UpdateWrapper 使用常見陷阱和解決方案
概要
MyBatis-Plus是Mybatis的一個增強,簡化了Mybatis的開發(fā)過程,不僅保持了Mybatis原有的功能,而且在無代碼侵略下增加了許多的增強的功能,提供了豐富的CRUD操作,單表的CRUD操作幾乎無需編寫SQL語句。雖然Mybatis-Plus方便了開發(fā)者的開發(fā),但是也會遇到一些常見的陷阱和問題,了解這些潛在的陷阱并知道如何避免它們,可以幫助你更高效的和正確的使用Mybatis-Plus。本文中介紹的是UpdateWrapper的常見陷阱和對應(yīng)的解決方案。
常見陷阱與解決方案
在我們的業(yè)務(wù)場景中,常常需要更新多條數(shù)據(jù)。在使用 MyBatis-Plus 進(jìn)行更新操作時,由于錯誤地使用 UpdateWrapper,可能會導(dǎo)致數(shù)據(jù)更新出現(xiàn)不可預(yù)知的錯誤。這些錯誤包括條件重復(fù)使用、忽略邏輯刪除字段、拼寫錯誤、以及嵌套條件使用不當(dāng)?shù)葐栴}。
用戶表

1.條件重復(fù)使用導(dǎo)致更新錯誤
在使用Mybatis-Plus的 "UpdateWapeer" 時,如果在循環(huán)中重復(fù)使用一個 "UpdateWapeer" 對象,前一個循環(huán)中設(shè)置的條件和更新值會在后續(xù)的循環(huán)中繼續(xù)生效,可能會導(dǎo)致更新操作受前一次條件的影響,導(dǎo)致最終只更新了部分的數(shù)據(jù)。
假設(shè)我們有一個用戶表 'User' 需要根據(jù)不同用戶Id批量刪除用戶,采用邏輯刪除,如果我們在循環(huán)中使用同一個 ‘UpdateWarpper' 對象進(jìn)行操作,就可能會導(dǎo)致部分更新錯誤。
public void updateByIds(UserIdsPO po) {
List<Integer> userIds = po.getUserIds();
userIds.forEach(userId ->{
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("is_delete",1)
.eq("id", userId);
update(updateWrapper);
});
}在這個錯誤示例中,"UpdateWapeer" 在每次循環(huán)都會添加新的更新條件和設(shè)置值,導(dǎo)致前一次的條件和值影響后續(xù)的更新操作。這可能導(dǎo)致只有第一條數(shù)據(jù)被正確更新,后續(xù)的數(shù)據(jù)更新出現(xiàn)錯誤。

解決方案
為了避免重復(fù)使用導(dǎo)致更新錯誤,我們應(yīng)該在循環(huán)中創(chuàng)建一個新的 "UpdateWapeer" 對象,確保每次更新操作的條件和設(shè)置值是獨立的。
public void updateByIds(UserIdsPO po) {
List<Integer> userIds = po.getUserIds();
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
userIds.forEach(userId ->{
updateWrapper.set("is_delete",1)
.eq("id", userId);
update(updateWrapper);
});
}當(dāng)然建議不要再循環(huán)中去操作數(shù)據(jù)庫,因為這樣每次都要創(chuàng)建新的連接,向Mysql發(fā)送網(wǎng)絡(luò)請求,增加額外的開銷。建議批量操作,這樣就連接一次數(shù)據(jù)庫就好了,性能大大的提升。
public void updateByIds(UserIdsPO po) {
List<Integer> userIds = po.getUserIds();
//根據(jù)用戶id查詢用戶
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.in("id", userIds);
List<User> userList = list(queryWrapper);
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
List<User> updateList = new ArrayList<>();
userList.forEach(user ->{
updateWrapper.set("is_delete",1)
.eq("id", user.getId());
//將要修改的用戶添加到集合中
updateList.add(user);
});
//批量更新
updateBatchById(updateList);
}只要確保每一次循環(huán)都是新的 "UpdateWapeer" 對象,就能更新成功。

2.Sql注入風(fēng)險
直接拼接 SQL 語句時,可能會存在 SQL 注入風(fēng)險。攻擊者可以通過傳入惡意構(gòu)造的輸入,執(zhí)行未預(yù)期的 SQL 語句,導(dǎo)致數(shù)據(jù)泄露或破壞。
public void updateUserStatus(Long userId, String status) {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.setSql("status = '" + status + "'")
.eq("id", userId);
update(updateWrapper);
}解決方案
使用 MyBatis-Plus 提供的條件構(gòu)造器方法,避免手動拼接 SQL 語句,同時使用參數(shù)化查詢來防止 SQL 注入。
public void updateUserStatus(Long userId, String status) {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("status", status)
.eq("id", userId);
update(updateWrapper);
}3.嵌套條件使用不當(dāng)
在使用 and 和 or 嵌套條件時,如果嵌套條件使用不當(dāng),可能會導(dǎo)致條件邏輯錯誤,更新操作未達(dá)到預(yù)期效果。例如,條件 A and (B or C) 和 (A and B) or C 的邏輯是不同的,不正確的嵌套條件可能導(dǎo)致錯誤的更新結(jié)果。
public void updateUsersState(int state, int age) {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("state", state);
.lt("age", age).or().isNull("name");
update(updateWrapper);
} 在這個錯誤示例中,條件 lt("age", age) 和 isNull("name") 是通過 or 連接的,但沒有使用 and 進(jìn)行正確的嵌套,可能導(dǎo)致邏輯錯誤。
解決方案
通過使用 and 方法將條件正確嵌套,確保條件 lt("age", age) 和 isNull("name") 組合在一起,并與其他條件正確連接,從而實現(xiàn)預(yù)期的更新效果。
public void updateUsersState(int state, int age) {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("state", state)
.and(wrapper -> wrapper.lt("age", age).or().isNull("name"));
update(updateWrapper);
}4.條件未正確設(shè)置導(dǎo)致全表更新
有時候我們需要批量更新用戶的狀態(tài)。如果沒有設(shè)置任何條件,可能會導(dǎo)致全表更新,造成嚴(yán)重的后果。
public void updateAllUsersState(int state) {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("state", state);
update(updateWrapper);
}在這個錯誤示例中,如果未設(shè)置任何條件,可能會導(dǎo)致全表更新。
解決方案
始終確保設(shè)置了適當(dāng)?shù)臈l件,或者在更新前進(jìn)行條件檢查。
public void updateUserStateById(Long userId, int state) {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("state", state)
.eq("id", userId);
update(updateWrapper);
}5.列名拼寫錯誤
在使用 UpdateWrapper 時,如果列名拼寫錯誤,可能會導(dǎo)致 SQL 語法錯誤或更新操作沒有預(yù)期效果。拼寫錯誤會導(dǎo)致生成的 SQL 語句不正確,從而無法執(zhí)行預(yù)期的更新操作。
public void updateUserName(Long userId, String newName) {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("nmae", newName) // 拼寫錯誤
.eq("id", userId);
update(updateWrapper);
}解決方案
通過使用 LambdaUpdateWrapper,可以避免列名拼寫錯誤,因為它使用實體類的字段而不是字符串來指定列名。
public void updateUserName(Long userId, String newName) {
LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.set(User::getName, newName);
.eq(User::getId, userId);
update(lambdaUpdateWrapper);
}小結(jié)
通過避免這些潛在的問題,提高我們的數(shù)據(jù)庫操作的安全性和效率,有效地防止這些問題。
到此這篇關(guān)于MyBatis-Plus UpdateWrapper 使用攻略的文章就介紹到這了,更多相關(guān)MyBatis-Plus UpdateWrapper 使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java定時任務(wù):利用java Timer類實現(xiàn)定時執(zhí)行任務(wù)的功能
本篇文章主要介紹了利用java Timer類實現(xiàn)定時執(zhí)行任務(wù)的功能,具有一定的參考價值,有需要的可以了解一下。2016-11-11
Spring配置多個數(shù)據(jù)源并實現(xiàn)數(shù)據(jù)源的動態(tài)切換功能
這篇文章主要介紹了Spring配置多個數(shù)據(jù)源并實現(xiàn)數(shù)據(jù)源的動態(tài)切換功能,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-01-01
java統(tǒng)計漢字字?jǐn)?shù)的方法示例
這篇文章主要介紹了java統(tǒng)計漢字字?jǐn)?shù)的方法,結(jié)合實例形式分析了java正則判定、字符串遍歷及統(tǒng)計相關(guān)操作技巧,需要的朋友可以參考下2017-05-05
SpringBoot如何使用@Aspect注解實現(xiàn)AOP
Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之背包問題
JFinal使用ajaxfileupload實現(xiàn)圖片上傳及預(yù)覽
詳解SpringBoot結(jié)合swagger2快速生成簡單的接口文檔

