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 分钟前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
心之语歌2 小时前
基于注解+拦截器的API动态路由实现方案
java·后端
华仔啊4 小时前
Stream 代码越写越难看?JDFrame 让 Java 逻辑回归优雅
java·后端
ray_liang4 小时前
用六边形架构与整洁架构对比是伪命题?
java·架构
Ray Liang5 小时前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
Java水解5 小时前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
SimonKing9 小时前
OpenCode AI辅助编程,不一样的编程思路,不写一行代码
java·后端·程序员
FastBean10 小时前
Jackson View Extension Spring Boot Starter
java·后端
Seven9711 小时前
剑指offer-79、最⻓不含重复字符的⼦字符串
java
皮皮林55120 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java