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