Mybatis-plus 更新 Null 的策略踩坑记

一个bug

在一个管理页面,有一个非必填字段被设置成空了并提交更新,再次打开的时候,发现字段还在,并没有被更新成功。

使用的数据库映射框架是 Mybatis-plus ,对于Mybatis 在更新字段的时候会对空进行校验,如果字段为 null,会被忽略加入 sql。

应对策略

推荐策略:使用 UpdateWrapper (3.x)

使用 UpdateWrapper 或 LambdaUpdateWrapper

这是官方给出的案例

less 复制代码
//updateAllColumnById(entity) // 全部字段更新: 3.0已经移除
mapper.update(
   new User().setName("mp").setAge(3),
   Wrappers.<User>lambdaUpdate()
           .set(User::getEmail, null) //把email设置成null
           .eq(User::getId, 2)
);
//也可以参考下面这种写法
mapper.update(
    null,
    Wrappers.<User>lambdaUpdate()
       .set(User::getAge, 3)
       .set(User::getName, "mp")
       .set(User::getEmail, null) //把email设置成null
       .eq(User::getId, 2)
);

通过这种方式,可以达到将字段设置成 null 的效果。

其他策略(不推荐并且慎用)

在字段上增加了 @TableField(updateStrategy = FieldStrategy.IGNORED)

在 DO 字段上添加这个更新策略,就是不会判断 null,任何时候都加入 sql

特别注意:这个策略,在高级版本中已经被 deprecated (3.5.3.2)

更新丢失风险 FieldStrategy.ALWAYS

意味着在每次更新操作中,都会将实体对象中的所有字段值写入数据库,无论这些字段的值是否为 null

风险巨大。

有一张用户表, 在 salary 上添加 FieldStrategy.ALWAYS

(id,name,age,salary)

开发A:通过 id 更新 age, 但是 DO 没有设置 salary了,mybaits-plus 会添加 salary ,最终导致 salary 被更新为 null,导致数据丢失。

这种问题如果不注意,后果十分严重,不建议在 DO 上添加此策略。随着业务发展,人员变动,这种操作会给以后埋下隐患。

另外使用这种策略以后,对于批量更新简直噩梦!慎重!

自定义 sql 方式

如果需要更复杂的逻辑来决定何时将字段设置为 null,可以选择编写自定义的 XML 映射文件或者使用 @Select, @Update 等注解来定义 SQL 语句,在其中明确写出 SET column_name = NULL

其他策略("曲线救国")

如果是 String 类型,可以设置成"",例如: MapStruct 设置一个默认值。

less 复制代码
@Mappings({
        @Mapping(source = "name", target = "name", defaultValue = "")
})
UpdateParam convert(Request request);

结束

  1. 谨慎使用策略 FieldStrategy.ALWAYS/ FieldStrategy.IGNORED
  2. 更新使用 UpdateWrapper 或 LambdaUpdateWrapper
相关推荐
null or notnull25 分钟前
idea对jar包内容进行反编译
java·ide·intellij-idea·jar
言午coding2 小时前
【性能优化专题系列】利用CompletableFuture优化多接口调用场景下的性能
java·性能优化
幸好我会魔法2 小时前
人格分裂(交互问答)-小白想懂Elasticsearch
大数据·spring boot·后端·elasticsearch·搜索引擎·全文检索
SomeB1oody2 小时前
【Rust自学】15.2. Deref trait Pt.1:什么是Deref、解引用运算符*与实现Deref trait
开发语言·后端·rust
缘友一世2 小时前
JAVA设计模式:依赖倒转原则(DIP)在Spring框架中的实践体现
java·spring·依赖倒置原则
何中应2 小时前
从管道符到Java编程
java·spring boot·后端
SummerGao.3 小时前
springboot 调用 c++生成的so库文件
java·c++·.so
组合缺一3 小时前
Solon Cloud Gateway 开发:Route 的过滤器与定制
java·后端·gateway·reactor·solon
SomeB1oody3 小时前
【Rust自学】15.4. Drop trait:告别手动清理,释放即安全
开发语言·后端·rust
我是苏苏3 小时前
C#高级:常用的扩展方法大全
java·windows·c#