一、问题背景
在使用 MyBatis-Plus 进行更新操作时,我们常常会写出如下代码:
User user = new User();
user.setId(1L);
user.setEmail(null);
userService.updateById(user);
本意是希望将用户 ID 为 1 的那条记录的 email 字段更新为 NULL,
但执行后发现 —— 数据库中的 email 并没有被置空!
很多开发者第一次遇到这个问题都会疑惑:
“明明 set 了 null,为什么没更新?”
要理解这个行为,我们先得了解 MyBatis-Plus 的默认更新策略。
二、默认行为:忽略 null 字段
MyBatis-Plus 默认在执行 updateById() 或 update() 时,会忽略掉值为 null 的字段。
这是由其内置的 字段更新策略(FieldStrategy) 决定的。
默认配置如下:
mybatis-plus:
global-config:
db-config:
update-strategy: not_null
含义:
仅当字段的值 不为 null 时,才会出现在 SQL 的 SET 子句中。
举例说明:
User user = new User();
user.setId(1L);
user.setEmail(null);
user.setNickname("Tom");
userService.updateById(user);
生成的 SQL 大致如下:
UPDATE user SET nickname = 'Tom' WHERE id = 1;
而不会包含 email = NULL。
三、解决方案:让 null 也能更新
想要让字段被更新为 null,有几种方式👇
✅ 方式一:全局修改更新策略
在 application.yml 中添加以下配置:
mybatis-plus:
global-config:
db-config:
update-strategy: always
always 表示:无论字段值是否为 null,均参与更新。
示例:
User user = new User();
user.setId(1L);
user.setEmail(null);
userService.updateById(user);
生成 SQL:
UPDATE user SET email = NULL WHERE id = 1;
适合场景:
全局业务逻辑都允许将字段更新为 null。
一、问题背景
在使用 MyBatis-Plus 进行更新操作时,我们常常会写出如下代码:
User user = new User();
user.setId(1L);
user.setEmail(null);
userService.updateById(user);
本意是希望将用户 ID 为 1 的那条记录的 email 字段更新为 NULL,
但执行后发现 —— 数据库中的 email 并没有被置空!
很多开发者第一次遇到这个问题都会疑惑:
“明明 set 了 null,为什么没更新?”
要理解这个行为,我们先得了解 MyBatis-Plus 的默认更新策略。
二、默认行为:忽略 null 字段
MyBatis-Plus 默认在执行 updateById() 或 update() 时,会忽略掉值为 null 的字段。
这是由其内置的 字段更新策略(FieldStrategy) 决定的。
默认配置如下:
mybatis-plus:
global-config:
db-config:
update-strategy: not_null
含义:
仅当字段的值 不为 null 时,才会出现在 SQL 的 SET 子句中。
举例说明:
User user = new User();
user.setId(1L);
user.setEmail(null);
user.setNickname("Tom");
userService.updateById(user);
生成的 SQL 大致如下:
UPDATE user SET nickname = 'Tom' WHERE id = 1;
而不会包含 email = NULL。
三、解决方案:让 null 也能更新
想要让字段被更新为 null,有几种方式👇
✅ 方式一:全局修改更新策略
在 application.yml 中添加以下配置:
mybatis-plus:
global-config:
db-config:
update-strategy: always
always 表示:无论字段值是否为 null,均参与更新。
示例:
User user = new User();
user.setId(1L);
user.setEmail(null);
userService.updateById(user);
生成 SQL:
UPDATE user SET email = NULL WHERE id = 1;
适合场景:
全局业务逻辑都允许将字段更新为 null。
注意:
此配置会影响所有实体更新操作,需谨慎使用。
✅ 方式二:局部控制(推荐)
可以在实体类字段上单独设置策略:
@Data
public class User {
private Long id;
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String email;
private String nickname;
}
这样,当执行更新时,即便 email 为 null,也会更新。
优势:
灵活、精细控制,仅影响特定字段。
✅ 方式三:使用 UpdateWrapper 手动指定字段
有时候不想改配置,也不方便改实体,可以使用 UpdateWrapper 手动设置:
userService.update(
null,
new UpdateWrapper<User>()
.eq("id", 1L)
.set("email", null)
);
生成 SQL:
UPDATE user SET email = NULL WHERE id = 1;
适合场景:
临时性更新,或只需更新部分字段。
四、实践建议
| 场景 |
推荐方案 |
| 全局都允许更新为 null |
全局配置 update-strategy: always |
| 仅部分字段允许置空 |
在字段上使用 @TableField(updateStrategy = FieldStrategy.ALWAYS) |
| 临时更新为 null |
使用 UpdateWrapper.set("字段", null) |
五、小结
MyBatis-Plus 默认会跳过 null 字段的更新,这是为了防止误更新。
但在某些业务场景下,我们确实需要“清空”字段值。
关键点总结如下:
- 默认策略是
not_null,null 值会被忽略;
- 可以通过全局或字段级配置改为
always;
- 也可以使用
UpdateWrapper.set() 手动置空。
掌握这三种方法,就能灵活应对各种更新需求,让 MyBatis-Plus 真正“听你的话”。
💡延伸阅读: