MyBatis-Plus 自动填充与更新策略知识清单
核心目的: 自动化处理实体类中公共字段(如创建时间、创建人、更新时间、更新人、租户ID、门店ID等)在插入和更新操作时的赋值,以及控制字段在更新时的行为。
三大关键组件:
-
MetaObjectHandler (元数据对象处理器)
-
角色: 执行者。提供自动填充的具体逻辑实现。
-
本质: 一个需要用户自己实现的接口 (com.baomidou.mybatisplus.core.handlers.MetaObjectHandler)。
-
核心方法:
- insertFill(MetaObject metaObject): 在执行标准 MP 插入操作 (insert(), save(), saveBatch() 等) 之前被调用。
- updateFill(MetaObject metaObject): 在执行标准 MP 更新操作 (updateById(), update(), saveOrUpdate() 的更新部分等) 之前被调用。
-
MetaObject metaObject: 代表当前正在操作的实体对象,可以通过它安全地获取和设置字段值。推荐使用 strictInsertFill/strictUpdateFill 或 setFieldValByName 方法。
-
实现要求:
- 必须实现 MetaObjectHandler 接口。
- 必须将其注册为 Spring Bean (通常使用 @Component 注解),MP 才能发现并使用它。
-
-
@TableField(fill = ...) (自动填充时机)
-
角色: 触发器标记。标记在实体类的具体字段上,告诉 MetaObjectHandler 何时应该尝试填充该字段。
-
位置: @TableField 注解的一个属性。
-
可选值 (FieldFill 枚举):
- DEFAULT: 不自动填充(默认值)。
- INSERT: 仅在插入时调用 MetaObjectHandler.insertFill() 尝试填充此字段。
- UPDATE: 仅在更新时调用 MetaObjectHandler.updateFill() 尝试填充此字段。
- INSERT_UPDATE: 插入时调用 insertFill(),更新时调用 updateFill(),都会尝试填充此字段。
-
依赖关系: 如果一个字段没有设置 fill 属性(或为 DEFAULT),即使 MetaObjectHandler 中有逻辑,也不会对该字段生效。
-
-
@TableField(updateStrategy = ...) (字段更新策略)
-
角色: 更新 SQL 控制器。标记在实体类的具体字段上,决定该字段是否包含在 MP 自动生成的标准 UPDATE 语句的 SET 子句中。
-
位置: @TableField 注解的另一个属性。
-
可选值 (FieldStrategy 枚举):
- ALWAYS: 无论字段值是否为 null,总是包含在 SET 子句中。
- NOT_NULL: 仅当字段的 Java 值不为 null 时,包含在 SET 子句中 (通常是默认策略)。
- NOT_EMPTY: 仅当字段为 String 类型且不为空字符串,或者非 String 类型且不为 null 时,包含在 SET 子句中。
- DEFAULT: 使用全局配置的默认策略 (通常是 NOT_NULL)。
- NEVER: 永远不将此字段包含在 SET 子句中,即使 Java 对象中有值。
-
交互关系与工作流程 (针对标准 MP 操作):
-
调用: 代码调用 MP 的标准 insert 或 update 方法。
-
分析: MP 分析实体类注解。
-
填充 (Insert/Update 前):
- 检查字段是否有 @TableField(fill = ...) 注解 (非 DEFAULT)。
- 如果有,根据 fill 的值 (INSERT, UPDATE, INSERT_UPDATE) 决定是否调用已注册的 MetaObjectHandler 的 insertFill() 或 updateFill() 方法。
- MetaObjectHandler 执行填充逻辑,修改 metaObject (即实体对象) 中对应字段的值。
-
SQL 生成 (Update 时):
- MP 准备生成 UPDATE ... SET ... WHERE ... 语句。
- 对于每个非主键字段,检查 @TableField(updateStrategy = ...) 的设置。
- 根据策略 (e.g., NOT_NULL, NEVER) 决定是否将该字段及其当前值(可能已被 updateFill 修改过)加入 SET 子句。
-
SQL 执行: 执行最终生成的 SQL 语句。
关键点与常见模式:
-
协同工作: fill 和 MetaObjectHandler 必须配合使用才能实现自动填充。
-
updateStrategy 独立性: updateStrategy 控制的是 SQL 生成,与 fill 是独立但相关的概念。
-
创建字段模式: 对于 createTime, createBy 等字段,常用组合是:
@TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER) private Date createTime;
解释:插入时自动填充 (fill = INSERT),并且在任何更新操作中永远不修改该字段 (updateStrategy = NEVER)。
-
更新字段模式: 对于 updateTime, updateBy 等字段,常用:
@TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时都填充 private Date updateTime;
updateStrategy 通常使用默认 (NOT_NULL) 或根据需要调整。
-
适用范围: 这套机制主要作用于基于实体操作的标准 MP 方法。对于自定义 Mapper XML 中的 SQL 语句,它们通常不起作用(MetaObjectHandler 可能有限介入 insert/update,但不稳定;updateStrategy 无效)。