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(特殊场景)。

相关推荐
shoubepatien4 小时前
JavaWeb_Maven
java·maven
逸风尊者4 小时前
开发可掌握的知识:推荐系统
java·后端·算法
IT方大同4 小时前
C语言选择控制结构
c语言·开发语言
名誉寒冰4 小时前
深入理解fd_set:从基础到实战应用(Linux/C++)
java·linux·c++
CodeAmaz4 小时前
RocketMQ怎么保证消息不丢失详解
java·rocketmq·java-rocketmq
A24207349304 小时前
js模糊搜索
开发语言·javascript·ecmascript
Darkershadow5 小时前
Python学习之使用pycharts
开发语言·python
灵魂猎手5 小时前
Antrl4 入门 —— 使用Antrl4实现一个表达式计算器
java·后端
晚秋大魔王5 小时前
C语言-宏的基础、进阶、高级、内置宏的用法
c语言·开发语言·
zhonghua8810165 小时前
spring ai alibab agent之ReactAgent深度解读
java·人工智能·spring