Mybatis-Plus更新操作时遇到的问题及解决方法

 更新时间:2026年01月19日 08:52:20   作者:Marktowin  
在MyBatis-Plus开启逻辑删除时,使用updateById更新逻辑删除字段时,可能会出现看起来执行了但实际上没有更新的问题,下面给大家介绍Mybatis-Plus更新操作时遇到的问题及解决方法,感兴趣的朋友跟随小编一起看看吧

在 MyBatis-Plus开启逻辑删除 的情况下,updateById更新逻辑删除字段时, “看起来执行了但实际上没有更新”的问题是一种较为常见但不易察觉的问题。

背景:

项目中使用mybatis-plus且已开启逻辑删除:

 mybatis-plus:
   global-config:
     db-config:
       logic-delete-field: deleted
       logic-delete-value: 1
       logic-not-delete-value: 0
       update-strategy: not_empty   #更新策略只更新非空

在代码中获取记录并更新逻辑删除字段:

 useRecord record = RecordMapper.selectOne(...); 
 record.setDeleted(1);
 RecordMapper.updateById(record);

执行结果没有明显报错,也不会有异常日志,但实际没有更新逻辑删除字段。

如果没有记录执行返回值进行判断,将导致逻辑删除失败问题被隐藏,为后续业务埋雷。

原因分析:

mybatis-plus使用逻辑删除背景下,使用updateById时,如下代码段:

 record.setDeleted(1);
 RecordMapper.updateById(record);

执行的sql语句是:

 UPDATE table_name 
 SET deleted = 1 
 WHERE id = ? 
   AND deleted = 0;  -- ⚠️ MyBatis-Plus 自动添加的条件

这条 SQL 在语法层面是合法的,但在 MyBatis-Plus 的设计语义中,逻辑删除并不被视为一次普通的 update 操作。

MyBatis-Plus 将“删除”与“更新”在内部逻辑上进行了区分:updateById 被设计为只能作用于“未被逻辑删除的数据”,而逻辑删除本身应通过 delete 系列方法触发。

 -- 你期望生成的SQL(框架不会生成)
 UPDATE record SET deleted = 1 WHERE id = ? AND deleted = 0;
 -- updateById实际生成的SQL(deleted字段被剔除)
 UPDATE record SET other_field=? WHERE id = ? AND deleted = 0;

Mybatis-Plus为什么要这样设计:

MyBtis-Plus 遵循 "语义隔离" 原则

操作类型框架方法SQL语义设计意图
业务更新updateById()修改业务字段只改数据内容,不改数据状态
逻辑删除deleteById()UPDATE ... SET deleted=1标记数据为"已删除"状态

关键机制:

  • 拦截器过滤:LogicDeleteInterceptor 会自动移除 SET 子句中的逻辑删除字段
  • 条件追加:所有查询/更新操作都会自动追加AND deleted = 0
  • 单向操作:逻辑删除被视为不可逆操作(删除后不应通过业务代码恢复)

如何正确处理:

  • 使用 MyBatis-Plus 提供的 deleteById 进行逻辑删除
 // 框架会自动生成:UPDATE user SET deleted=1 WHERE id=? AND deleted=0
 recordMapper.deleteById(1L); 

  在开启逻辑删除的前提下,deleteById 不会执行物理删除,而是由 MyBatis-Plus 自动生成逻辑删除 SQL,其语义与框架设计完全一致。

  • 用 LambdaUpdateWrapper 显式执行逻辑删除
  // 手动指定SET子句,绕过字段过滤
 LambdaUpdateWrapper<Record> wrapper = new LambdaUpdateWrapper<>();
 wrapper.eq(Record::getId, 1L).set(Record::getDeleted, 1); // 强制设置deleted字段
 recordMapper.update(null, wrapper);

  如果业务上必须通过 update 的方式完成逻辑删除,可以使用 LambdaUpdateWrapper,自行控制 WHERE 条件,避免与 MyBatis-Plus 的自动逻辑删除条件产生冲突。此方式绕过了 updateById 的内置逻辑删除约束,应明确其用途,避免被误用为普通更新。

  • 自定义 SQL 明确逻辑删除语
 @Update("UPDATE record SET deleted = 1 WHERE id = #{id} AND deleted = 0")
 int logicDeleteById(Long id);

  适合对逻辑删除行为有强语义要求的项目,便于代码阅读和后期维护。

总结:

在 MyBatis-Plus 中,逻辑删除不是一次普通的字段更新操作。updateById 被设计为只能更新“未被逻辑删除的数据”,而不用于触发逻辑删除本身。当更新语句同时在 SET 和 WHERE 中涉及逻辑删除字段时,就会与框架的设计语义产生冲突。正确的做法是使用 delete 系列方法,或通过 Wrapper / 自定义 SQL 明确表达“逻辑删除”的意图。

到此这篇关于Mybatis-Plus更新操作时的一个坑的文章就介绍到这了,更多相关Mybatis-Plus更新操作时的一个坑内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Intellij IDEA中如何查看maven项目中所有jar包的依赖关系图

    Intellij IDEA中如何查看maven项目中所有jar包的依赖关系图

    这篇文章主要介绍了Intellij IDEA中如何查看maven项目中所有jar包的依赖关系图,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • java实现RedisTemplate操作哈希数据

    java实现RedisTemplate操作哈希数据

    RedisTemplate是Spring Data Redis提供的一个用于操作Redis的模板类,本文主要介绍了java实现RedisTemplate操作哈希数据,具有一定的参考价值,感兴趣的可以了解一下
    2024-09-09
  • Springmvc基于fastjson实现导包及配置文件

    Springmvc基于fastjson实现导包及配置文件

    这篇文章主要介绍了Springmvc基于fastjson实现导包及配置文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Java运行时多态性的实现

    Java运行时多态性的实现

    Java运行时多态性的实现...
    2006-12-12
  • Gateway 中是否能写 Servlet Filter

    Gateway 中是否能写 Servlet Filter

    在SpringCloudGateway中不能使用ServletFilter,因为它是基于Reactor模型构建的,底层用的是Netty,而不是Tomcat、Jetty这些Servlet容器,要实现类似功能,请用GlobalFilter或GatewayFilter,本文给大家解析Gateway中能写Servlet Filter吗,感兴趣的朋友一起看看吧
    2025-12-12
  • RabbitMQ中的Channel和Exchange详解

    RabbitMQ中的Channel和Exchange详解

    这篇文章主要介绍了RabbitMQ中的Channel和Exchange详解,创建和销毁TCP连接很耗时,打开太多TCP连接,耗操作系统资源,并发量大到一定程度,系统的吞吐量会降低,使用一个connection多channel的方式,可以提升连接的利用率,需要的朋友可以参考下
    2023-08-08
  • Java使用map实现带过期时间的缓存机制

    Java使用map实现带过期时间的缓存机制

    在 Java 开发领域,缓存机制的构建通常依赖于 Redis 等专业缓存数据库,这类解决方案虽能提供强大的缓存能力,但引入中间件意味着增加系统架构复杂度、部署成本与运维负担,本文将深入探讨一种轻量级替代方案基于 Java 原生Map实现的带过期时间的缓存机制
    2025-04-04
  • Java语言基于无向有权图实现克鲁斯卡尔算法代码示例

    Java语言基于无向有权图实现克鲁斯卡尔算法代码示例

    这篇文章主要介绍了Java语言基于无向有权图实现克鲁斯卡尔算法代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • springboot集成mybatis官方生成器

    springboot集成mybatis官方生成器

    本文主要介绍了springboot集成mybatis官方生成器,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • springboot接入方式对接股票数据源API接口的操作方法

    springboot接入方式对接股票数据源API接口的操作方法

    本文介绍了如何使用Java语言创建一个项目来对接StockTV的API接口,包括使用HttpURLConnection或OkHttp发送HTTP请求,使用Java-WebSocket库处理WebSocket连接等步骤,项目结构包括添加依赖、创建基础工具类、实现股票API、外汇API等,感兴趣的朋友一起看看吧
    2025-03-03

最新评论