MyBatis-Plus 更新字段为 null 被忽略?小白也能懂的解决方案

在使用 MyBatis-Plus 进行数据库更新时,很多小伙伴会遇到一个问题:

当某个字段传了 null 时,updateById 默认 不会更新该字段,数据库里的值依然保留。

这个问题在你想把字段置空时就会很麻烦。下面我给大家讲几个解决方案,小白也能快速上手。


问题示例

假设我们有一个更新方法:

@Override
@Transactional(rollbackFor = Exception.class)
public void updateCarousel(@Valid CarouselUpdateReqVO updateReqVO) {
    // 校验记录存在
    validateCarouselExists(updateReqVO.getId());

    // 转换实体类
    CarouselDO updateObj = BeanUtils.toBean(updateReqVO, CarouselDO.class);

    // 更新数据库
    carouselMapper.updateById(updateObj);
}

如果 updateReqVO.getLinkId()null,执行 updateById 后,link_id 不会被更新,数据库值不会变成 null

这是 MyBatis-Plus 默认策略导致的,它默认 忽略 null 值字段


方案 1:修改实体类策略,让 null 也更新

MyBatis-Plus 提供了 @TableField(updateStrategy = FieldStrategy) 来控制字段更新策略。

import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;

@TableField(updateStrategy = FieldStrategy.ALWAYS)
private Long linkId;

策略说明:

策略作用
ALWAYS永远更新,即使字段为 null,也会更新到数据库
NOT_NULL默认值,字段为 null 时不会更新
NOT_EMPTY字符串类型使用,空字符串也会忽略
NEVER永不更新
DEFAULT使用全局默认策略

✅ 如果字段使用 ALWAYS,当你传 null 时,就会把数据库字段置空。

优点:简单直接,只需改实体类。
缺点:全局生效,可能影响其它更新场景。


方案 2:使用 UpdateWrapper 或 LambdaUpdateWrapper 动态更新

如果你只想在某次更新操作中支持 null 更新,而不改实体类,可以手动构建更新条件:

CarouselDO updateObj = BeanUtils.toBean(updateReqVO, CarouselDO.class);

LambdaUpdateWrapper<CarouselDO> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(CarouselDO::getId, updateObj.getId())
       .set(CarouselDO::getLinkId, updateObj.getLinkId()); // null 也可以更新

carouselMapper.update(null, wrapper);

或者使用普通 UpdateWrapper:

UpdateWrapper<CarouselDO> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", updateObj.getId())
             .set("link_id", updateObj.getLinkId()); // null 也可以更新

carouselMapper.update(updateObj, updateWrapper);

✅ 优点:灵活,只针对当前更新操作生效。
❌ 缺点:字段较多时,需要手动写每个字段。


方案 3:自定义 Mapper SQL

当字段较多或者更新规则复杂时,可以直接写自定义 SQL:

<update id="updateCarousel">
    update carousel
    set
        link_id = #{linkId},
        title = #{title},
        description = #{description}
    where id = #{id}
</update>

✅ 完全控制字段更新规则,包括 null 值。
❌ 失去 MyBatis-Plus 自动映射便利。


小结

方案优点缺点适用场景
实体类设置 ALWAYS简单,全局生效影响所有更新操作字段允许全局置空
LambdaUpdateWrapper / UpdateWrapper灵活,针对单次操作写法稍复杂单次更新可能置空字段
自定义 Mapper SQL完全控制,适合复杂场景失去自动映射批量或复杂更新

💡 推荐做法

  • 偶尔置空 → 用 方案 2
  • 经常置空 → 用 方案 1
  • 更新逻辑复杂 → 用 方案 3

总结

MyBatis-Plus 默认忽略 null 值是为了安全,但当你需要置空数据库字段时,需要使用 FieldStrategy.ALWAYS 或手动更新。

掌握这几种方式后,你就能灵活处理 null 值字段更新,不再受默认策略限制。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值