1011 字
约 3 分钟
7
S08-B04 · MyBatis-Plus 基础:CRUD、注解、逻辑删除

适用读者:手写 CRUD 写到烦的人。
前置:S08-B01。
实测环境:MyBatis-Plus 3.5.7(Boot 3 starter)/ H2(2026-11-05)。
覆盖旧文:1170(41) 495(41) 1171(40) 1172(59) 1173(19) 1178(108) 1177(47) 1176(52) 1175(109) 1182(58) 1186(40) 1188(50) 1187(58) 1189(72) 351(62) 152(59) 1174(46) = 986 点。
覆盖扩展:E-S08-016(MP 与 MyBatis 的关系)。
上一篇:S08-B03 · 动态 SQL:<if> / <where> / <foreach>
下一篇:S08-B05 · Wrapper。


1. 一句话结论

MyBatis-Plus 不是另一个 ORM,它是"在 MyBatis 之上加了一层 CRUD 模板 + 若干内置拦截器"。所以 MyBatis 能做的它都能做,它多出来的是"少写代码"。

能力 MyBatis MyBatis-Plus
SQL 控制 完全手写 手写 + 通用 CRUD
逻辑删除 手写 where deleted=0 @TableLogic 自动
乐观锁 手写 version 条件 @Version 自动
分页 PageHelper 等 内置分页插件
代码生成 无 AutoGenerator(→S06)

2. 实测:一次 CRUD 生成的 SQL

@TableName("sys_user")
public class User { @TableId(type = IdType.AUTO) Long id; String userName; Integer age;
                    @TableLogic Integer deleted; @Version Integer version; }
public interface UserMapper extends BaseMapper<User> {}

实测输出:

1. 插入 3 条 → 3
2. Wrapper 条件 age>=20 且 name like a → [User(1,alice,20,del=0,ver=0), User(3,carol,20,del=0,ver=0)]
3. 更新后 version → 1
4. 逻辑删除后 selectList 条数 → 2

对应 SQL(实测打印):

INSERT INTO sys_user ( user_name, age ) VALUES ( ?, ? )
SELECT id,user_name,age,deleted,version FROM sys_user WHERE deleted=0
UPDATE sys_user SET user_name=?, age=?, version=? WHERE id=? AND version=? AND deleted=0
UPDATE sys_user SET deleted=1 WHERE id=? AND deleted=0

三条最值得注意:

观察 结论
每个 SELECT 都带 deleted=0 逻辑删除是"自动追加条件",不是真删除
UPDATE 带 version=? 双重条件 乐观锁,版本不符则影响 0 行
DELETE 变成 UPDATE 物理行还在

3. 逻辑删除 vs 物理删除

维度 逻辑删除(@TableLogic) 物理删除
数据可恢复 ✅ ❌
表会膨胀 ✅(需归档策略) ❌
唯一索引 ⚠️ 要带 deleted 列(否则重复键冲突) 简单
查询性能 每查都多一个条件 略快

判据:"删除的数据要能找回/审计吗?" 要 → 逻辑删除;不要且量大 → 物理删除 + 备份。


4. 乐观锁(@Version)

update ... set version = version + 1 where id = ? and version = ?

实测:更新后 version 从 0 → 1。

注意点 说明
需要拦截器 OptimisticLockerInnerInterceptor
只对 updateById 生效 自定义 SQL 要自己带 version
冲突处理 影响行数 0 → 需重试或提示

5. 其他常用能力

注解/能力 作用
@TableId(type = AUTO/ASSIGN_ID/INPUT) 主键策略
@TableField(fill = INSERT) 自动填充(创建时间等)
@EnumValue 枚举映射(1186)
动态表名(DynamicTableNameInnerInterceptor) 按月分表(1189)
log-impl=StdOutImpl 打印 SQL 与参数(1174)

打印 SQL 的实测:配置 mybatis-plus.configuration.log-impl 后能看到 ==> Preparing 与 ==> Parameters——这是排障第一步。


6. 五个误区

误区 真相
"MP 会替代 MyBatis" 是增强,底层仍是 MyBatis
"逻辑删除等于真删除" 是 UPDATE
"加了 @Version 就自动乐观锁" 需要拦截器
"BaseMapper 能覆盖所有 SQL" 复杂 SQL 仍要手写
"MP 生成器代码可直接上线" 生成物需 Review(S06-J03)

7. 自检

  1. MP 与 MyBatis 的关系?
  2. 逻辑删除在 SQL 层是什么?
  3. 乐观锁的 WHERE 条件多了什么?冲突时怎么办?
  4. 逻辑删除对唯一索引有什么影响?
  5. 怎么打印 MP 执行的 SQL?

8. 下一篇

S08-B05 · Wrapper 条件构造器

MP 基础讲完,下一篇专讲"条件怎么组合":QueryWrapper/LambdaQueryWrapper 的用法与安全边界。


本篇属于系列《S08 · MyBatis 持久层》。旧文来源:A-1170/495/1171/1172/1173/1178/1177/1176/1175/1182/1186/1188/1187/1189/351/152/1174;扩展点 E-S08-016。SQL 与结果均为 MP 3.5.7 + H2 实测。

S08-B04 · MyBatis-Plus 基础:CRUD、注解、逻辑删除
https://www.clxhxhhr.top/posts/5285/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。