【基于mybatis-plus下更新指定字段为null?】

本文介绍了在Mybatis-Plus中如何针对特定字段设置更新值为null的方法,包括使用@TableField注解和Mapper的LambdaUpdateWrapper。了解如何避免全局影响并精确控制更新行为。

问题:基于mybatis-plus下更新指定字段为null


一、mybatis-plus是什么?

mybatis-plus简称:MP,是基于mybatis实现的增强插件。快速实现单表操作
特点:

  1. 免xml,全程不用xml文件,基于java代码实现
  2. 简单配置
  3. 集成代码生成,自动分页,逻辑删除等快捷开发方式

二、mybatis-plus下更新字段值为null

在使用Mybatis-plus的更新方法的时候,如果传递的参数中某个字段为null,会忽略当前字段值的更新,默认不会对为null的字段更新成null。但是我们有写场景下必须对单独的几个字段赋值为null,那么这种情况下怎么去实现呢?

1. @TableField 注解实现:

@TableField(updateStrategy= FieldStrategy.IGNORED)
private String name;
描述
IGNORED忽略判断
NOT_NULL非 NULL 判断
NOT_EMPTY非空判断(只对字符串类型字段,其他类型字段依然为非 NULL 判断)
DEFAULT追随全局配置
NEVER不加入SQL
-- FieldStrategy.IGNORED 忽略判断,相当于跳过对null值得判断,该更新什么就更新什么:
update student set name = null

调用Mapper.updateById(T entity)时,就可以插入null值了。
这中方式有个弊端,修改方式是全局的,影响updateById()方法的调用效果。

2. Mapper.update()方法实现:

与select方式一样,mybatis-plus也提供了update的UpdateWrapper方式:

	LambdaUpdateWrapper<StudentEntity> auw = new LambdaUpdateWrapper<>();
    auw.set(StudentEntity :: getName, null);
    auw.eq(StudentEntity :: getId, 1);
    this.mapper.update(null, auw); 
-- 这种方式指定更新字段和更新的值,相当于:
update student set name = null where id = 1

end

在使用 **MyBatis-Plus** 时,如果你希望只更新实体中的某些**指定字段**,而不是将整个实体的所有字段更新到数据库(避免 `null` 值覆盖),可以通过以下几种方式实现 **只 update 指定字段**。 --- ### ✅ 方法一:使用 `UpdateWrapper` + `set()` 显式指定字段(推荐) 这是最灵活、最安全的方式,**不依赖实体对象的属性值**,可以精确控制要更新哪些字段。 ```java LambdaUpdateWrapper<IoStatistics> wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(IoStatistics::getId, 123L) .set(IoStatistics::getReportDate, LocalDateTime.now()) .set(IoStatistics::getStatus, 1); // 执行更新 ioStatisticsMapper.update(null, wrapper); ``` #### 🔍 说明: - `update(null, wrapper)`:第一个参数传 `null` 表示不使用实体对象的数据。 - `.set(...)`:手动设置某个字段的值。 - 生成 SQL 示例: ```sql UPDATE io_statistics SET report_date = ?, status = ? WHERE id = 123; ``` > ⭐ 完全避免了 `null` 字段更新的问题,推荐用于精确更新场景。 --- ### ✅ 方法二:使用 `UpdateWrapper` 结合实体对象(部分字段赋值) 先给实体对象设置你要更新字段,其他字段保持为 `null` 或默认值,然后配合 `UpdateWrapper` 使用。 ```java IoStatistics statistics = new IoStatistics(); statistics.setId(123L); // 主键用于 where 条件 statistics.setReportDate(LocalDateTime.now()); statistics.setStatus(1); LambdaUpdateWrapper<IoStatistics> wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(IoStatistics::getId, statistics.getId()); ioStatisticsMapper.update(statistics, wrapper); ``` > ⚠️ 注意:这种方式要求 MyBatis-Plus 的 **字段策略** 支持忽略 `null` 值。否则 `null` 字段可能会被更新成 `NULL`。 --- ### ✅ 方法三:配置字段更新策略(全局或字段级) 确保 `null` 字段不会参与更新,通过配置字段填充策略。 #### 方式 1:全局配置(application.yml) ```yaml mybatis-plus: global-config: db-config: field-strategy: NOT_NULL # INSERT 和 UPDATE 都不更新 null 字段(已废弃) # 新版本使用 insertStrategy / updateStrategy insert-strategy: NOT_NULL update-strategy: NOT_NULL ``` > ⚠️ 注意:`field-strategy` 在 **MyBatis-Plus 3.3.0+ 已废弃**,应使用: ```yaml mybatis-plus: configuration: # 全局配置字段更新策略 global-config: db-config: update-strategy: NOT_NULL ``` #### 方式 2:字段级别注解(更精细控制) ```java public class IoStatistics { private Long id; @TableField(updateStrategy = FieldStrategy.NOT_NULL) private LocalDateTime reportDate; @TableField(updateStrategy = FieldStrategy.NOT_NULL) private Integer status; } ``` 这样即使你传入了实体对象,只要字段是 `null`,就不会出现在 `UPDATE` 语句中。 --- ### ✅ 方法四:使用 `UpdateChainWrapper`(链式调用) 适合简单场景,代码更简洁: ```java boolean success = ioStatisticsService.lambdaUpdate() .eq(IoStatistics::getId, 123L) .set(IoStatistics::getReportDate, LocalDateTime.now()) .set(IoStatistics::getStatus, 2) .update(); if (success) { System.out.println("更新成功"); } ``` --- ### ❌ 错误做法(容易出问题) ```java IoStatistics entity = new IoStatistics(); entity.setId(123L); entity.setReportDate(null); // 这个 null 可能会把数据库字段置为 NULL! ioStatisticsMapper.updateById(entity); ``` > 如果没有正确配置 `updateStrategy`,这会导致 `report_date = NULL` 被执行! --- ### ✅ 推荐最佳实践总结 | 场景 | 推荐方法 | |------|----------| | 只更新几个字段,且不想动实体 | ✅ `LambdaUpdateWrapper` + `.set()` | | 更新一个实体的部分非空字段 | ✅ 实体 + `updateStrategy = NOT_NULL` | | 链式编程风格 | ✅ `lambdaUpdate().eq().set().update()` | | 批量更新指定字段 | ✅ `service.update(batchEntityList, updateWrapper)` | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值