saveOrUpdate 有个缺点,不会把值赋值为null,解决办法

针对 MyBatis-Plus 的 saveOrUpdate 方法无法将字段更新为 null 的问题,这是因为 MyBatis-Plus 默认会忽略 null 值字段。以下是几种解决方案:

方案 1:使用 update(entity, wrapper) 手动指定更新条件

原理 :通过 UpdateWrapper 明确指定需要更新为 null 的字段。

java 复制代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    public void updateWithNullValue() {
        User user = new User();
        user.setId(1L);
        user.setUsername(null); // 需要更新为 null 的字段

        // 手动构建 UpdateWrapper,强制更新 null 值字段
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.set("username", null) // 指定 username 字段更新为 null
               .eq("id", user.getId()); // 更新条件:ID = 1

        // 调用 update 方法,第一个参数可以为 null(因为条件已在 wrapper 中)
        boolean success = this.update(null, wrapper);
        if (success) {
            System.out.println("更新 null 值成功");
        }
    }
}

方案 2:配置全局字段策略(推荐)

原理 :通过配置 FieldStrategy 让 MyBatis-Plus 不忽略 null 值。

方式 1:配置文件(application.yml)
yaml 复制代码
mybatis-plus:
  global-config:
    db-config:
      update-strategy: IGNORED  # 更新策略:忽略判断,所有字段都更新(包括 null)
方式 2:Java 配置类
java 复制代码
@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 其他配置...
        
        // 配置全局策略
        GlobalConfig globalConfig = new GlobalConfig();
        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
        dbConfig.setUpdateStrategy(FieldStrategy.IGNORED); // 更新时忽略字段非空判断
        globalConfig.setDbConfig(dbConfig);
        
        return interceptor;
    }
}

方案 3:使用 @TableField 注解(细粒度控制)

原理 :在实体类字段上指定更新策略为 IGNORED

java 复制代码
@Data
@TableName("t_user")
public class User {
    @TableId
    private Long id;
    
    @TableField(updateStrategy = FieldStrategy.IGNORED) // 该字段更新时忽略 null 判断
    private String username;
    
    private String phone;
    
    @TableField(updateStrategy = FieldStrategy.IGNORED) // 该字段更新时忽略 null 判断
    private Integer age;
}

方案 4:自定义 SQL 方法

原理 :在 Mapper 接口中自定义更新方法,使用 @Update 注解编写 SQL。

java 复制代码
public interface UserMapper extends BaseMapper<User> {

    @Update("UPDATE t_user SET username = #{username}, age = #{age} WHERE id = #{id}")
    boolean updateWithNull(@Param("id") Long id, 
                          @Param("username") String username, 
                          @Param("age") Integer age);
}

Service 层调用

java 复制代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    public void customUpdateWithNull() {
        boolean success = baseMapper.updateWithNull(1L, null, 25);
        if (success) {
            System.out.println("自定义 SQL 更新 null 值成功");
        }
    }
}

总结

方案 优点 缺点 适用场景
方案 1 灵活,按需更新 代码冗余 少量需要更新 null 的场景
方案 2 全局生效,无需修改代码 影响所有实体 项目中大量需要更新 null
方案 3 细粒度控制,不影响其他字段 需修改实体类 部分字段需要更新 null
方案 4 完全自定义 SQL 维护成本高 复杂更新逻辑或性能敏感场景

推荐顺序:方案 3(细粒度控制)→ 方案 2(全局配置)→ 方案 1(临时需求)→ 方案 4(特殊场景)。

相关推荐
寻星探路4 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
lly2024066 小时前
Bootstrap 警告框
开发语言
2601_949146536 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧6 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
KYGALYX6 小时前
服务异步通信
开发语言·后端·微服务·ruby
zmzb01036 小时前
C++课后习题训练记录Day98
开发语言·c++
爬山算法7 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7257 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎7 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄7 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea