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更新操作时的一个坑内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MyBatis逆向⼯程的生成过程

    MyBatis逆向⼯程的生成过程

    MyBatis官方为我们提供了一个逆向工程,通过这个逆向工程,只要建立好数据表,那么MyBatis就会根据这个表自动生成pojo类、dao接口、sql映射文件
    2023-02-02
  • JPA CriteriaBuilder子查询方式

    JPA CriteriaBuilder子查询方式

    这篇文章主要介绍了JPA CriteriaBuilder子查询方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Spring Cloud Gateway 整合 knife4j 聚合接口文档功能

    Spring Cloud Gateway 整合 knife4j 聚合接口文档功能

    这篇文章主要介绍了Spring Cloud Gateway 整合 knife4j 聚合接口文档的相关知识,我们可以基于 Spring Cloud Gateway 网关 + nacos + knife4j 对所有微服务项目的接口文档进行聚合,从而实现我们想要的文档管理功能,需要的朋友可以参考下
    2022-02-02
  • java 抽象类示例详解

    java 抽象类示例详解

    我们将“只有方法声明,没有方法体”的一类方法统称为抽象方法,抽象方法用关键字abstract修饰,本文介绍java 抽象类示例详解,感兴趣的朋友跟随小编一起看看吧
    2024-12-12
  • 如何使用JAVA调用SHELL

    如何使用JAVA调用SHELL

    这篇文章主要介绍了如何使用JAVA调用SHELL,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • springboot中使用redis的方法代码详解

    springboot中使用redis的方法代码详解

    &#8203;redis 作为一个高性能的内存数据库,如果不会用就太落伍了,之前在 node.js 中用过 redis,本篇记录如何将 redis 集成到 spring boot 中。感兴趣的朋友跟随小编一起看看吧
    2019-05-05
  • 解决MyBatis中为类配置别名,列名与属性名不对应的问题

    解决MyBatis中为类配置别名,列名与属性名不对应的问题

    这篇文章主要介绍了解决MyBatis中为类配置别名,列名与属性名不对应的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • 详解Java中的Lambda表达式

    详解Java中的Lambda表达式

    这篇文章主要介绍了Java中的Lambda表达式的的相关资料,文中讲解非常详细,示例代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • springboot操作ldap全过程

    springboot操作ldap全过程

    这篇文章主要介绍了springboot操作ldap全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • 封装了一个Java数据库访问管理类

    封装了一个Java数据库访问管理类

    刚刚试着用JDBC,仿着原来C#的写法写了这段代码,自己觉得还是挺粗糙的,还烦请路过的朋友推荐一个写得较好较完整的相关例程以便学习。谢谢!
    2009-02-02

最新评论