MyBatis 本身不直接提供逻辑删除和自动填充功能,但可通过 MyBatis-Plus 或原生拦截器实现;MyBatis-Plus 通过 @TableLogic 注解和全局配置支持逻辑删除,通过 @TableField(fill = FieldFill.XXX) 与 MetaObjectHandler 实现自动填充;纯 MyBatis 需自定义拦截器或 Service 层封装;注意事项包括字段类型选择、批量更新处理及分页/联表/自定义 SQL 的手动适配。

MyBatis 本身不直接提供逻辑删除和自动填充功能,但通过 MyBatis-Plus(推荐)或结合 MyBatis 原生拦截器 + 注解 + 自定义 SQL 可以优雅实现。核心在于统一处理字段(如 is_deleted、create_time、update_time),避免在每个 DAO 层手动写。
用 MyBatis-Plus 实现逻辑删除
MyBatis-Plus 内置逻辑删除支持,只需简单配置:
- 在实体类对应字段上加
@TableLogic注解(如private Integer isDeleted;) - 在
application.yml中配置逻辑未删除值和已删除值:
mybatis-plus.global-config.db-config.logic-delete-value: 1
mybatis-plus.global-config.db-config.logic-not-delete-value: 0 - 启用后,所有
selectList、getById等查询自动追加AND is_deleted = 0;deleteById不执行物理删,而是执行UPDATE SET is_deleted = 1 - 如需物理删除(如后台管理),可用
removeWrapper(new LambdaQueryWrapper().setEntity(new Xxx()).eq(Xxx::getIsDeleted, 1))或调用baseMapper.delete()配合自定义 Wrapper
用 MyBatis-Plus 自动填充公共字段
基于 @TableField(fill = FieldFill.INSERT) 和 MetaObjectHandler 实现创建/更新时间、操作人等字段自动赋值:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 在实体字段上标注填充策略:
@TableField(fill = FieldFill.INSERT) private LocalDateTime createTime;@TableField(fill = FieldFill.UPDATE) private LocalDateTime updateTime; - 编写实现类继承
MetaObjectHandler,重写insertFill和updateFill方法:
在insertFill中对空的createTime、updateTime、createBy赋值;
在updateFill中只更新updateTime和updateBy(不覆盖createTime) - 注意:填充发生在 MyBatis-Plus 的 SQL 构建阶段,不是数据库触发器,所以值由 Java 层控制,便于集成当前登录用户信息
纯 MyBatis(无 MP)如何做?
若项目不能引入 MyBatis-Plus,可用以下组合方式:
-
逻辑删除:自定义
Interceptor拦截Executor.update和Executor.query,识别带@DeleteLogic或命名约定(如方法含Remove)的方法,改写 SQL —— 查询加WHERE is_deleted = 0,删除改为UPDATE ... SET is_deleted = 1 -
自动填充:同样用拦截器,在
Executor.update前解析MappedStatement和参数对象,反射设置createTime/updateTime;或更轻量——在 Service 层统一封装 BaseDTO,用 AOP 或模板方法提前填充 - 缺点是侵入性强、易出错,且需自行维护字段名与填充规则映射,不如 MyBatis-Plus 声明式直观
注意事项与最佳实践
实际落地时容易踩坑,需关注几点:
- 逻辑删除字段类型建议用
TINYINT(1)或BIT,避免用字符串(如 'Y'/'N'),否则索引效率低且易错拼 - 自动填充的
updateTime必须在每次更新时刷新,包括批量更新(MyBatis-Plus 默认支持,原生需确保 SQL 中显式 set) - 分页查询、联表查询、自定义 XML SQL 需手动补
AND is_deleted = 0,MP 的逻辑删除只对它生成的 SQL 生效 - 若用多租户 + 逻辑删除,注意两者过滤条件叠加顺序,避免被租户插件提前截断

















