iis網(wǎng)站日志今日國際新聞頭條新聞
一個bug
在一個管理頁面,有一個非必填字段被設(shè)置成空了并提交更新,再次打開的時候,發(fā)現(xiàn)字段還在,并沒有被更新成功。
使用的數(shù)據(jù)庫映射框架是 Mybatis-plus ,對于Mybatis 在更新字段的時候會對空進行校驗,如果字段為 null,會被忽略加入 sql。
應對策略
推薦策略:使用 UpdateWrapper
(3.x)
使用 UpdateWrapper 或 LambdaUpdateWrapper
這是官方給出的案例
//updateAllColumnById(entity) // 全部字段更新: 3.0已經(jīng)移除
mapper.update(new User().setName("mp").setAge(3),Wrappers.<User>lambdaUpdate().set(User::getEmail, null) //把email設(shè)置成null.eq(User::getId, 2)
);
//也可以參考下面這種寫法
mapper.update(null,Wrappers.<User>lambdaUpdate().set(User::getAge, 3).set(User::getName, "mp").set(User::getEmail, null) //把email設(shè)置成null.eq(User::getId, 2)
);
通過這種方式,可以達到將字段設(shè)置成 null 的效果。
其他策略(不推薦并且慎用)
在字段上增加了` @TableField(updateStrategy = FieldStrategy.IGNORED)`
在 DO 字段上添加這個更新策略,就是不會判斷 null,任何時候都加入 sql
特別注意:這個策略,在高級版本中已經(jīng)被 deprecated (3.5.3.2)
更新丟失風險 FieldStrategy.ALWAYS
意味著在每次更新操作中,都會將實體對象中的所有字段值寫入數(shù)據(jù)庫,無論這些字段的值是否為 null
風險巨大。
有一張用戶表, 在 salary 上添加 FieldStrategy.ALWAYS
(id,name,age,salary)
開發(fā)A:通過 id 更新 age, 但是 DO 沒有設(shè)置 salary了,mybaits-plus 會添加 salary ,最終導致 salary 被更新為 null,導致數(shù)據(jù)丟失。
這種問題如果不注意,后果十分嚴重,不建議在 DO 上添加此策略。隨著業(yè)務(wù)發(fā)展,人員變動,這種操作會給以后埋下隱患。
另外使用這種策略以后,對于批量更新簡直噩夢!慎重!
自定義 sql 方式
如果需要更復雜的邏輯來決定何時將字段設(shè)置為 null
,可以選擇編寫自定義的 XML 映射文件或者使用 @Select
, @Update
等注解來定義 SQL 語句,在其中明確寫出 SET column_name = NULL
其他策略(“曲線救國”)
如果是 String 類型,可以設(shè)置成“”,例如: MapStruct 設(shè)置一個默認值。
@Mappings({@Mapping(source = "name", target = "name", defaultValue = "")
})
UpdateParam convert(Request request);
結(jié)束
- 謹慎使用策略 FieldStrategy.ALWAYS/ FieldStrategy.IGNORED
- 更新使用 UpdateWrapper 或 LambdaUpdateWrapper