在软件开发中,实体类的公共字段(如 create_time、update_time、create_by、update_by 等)频繁需要根据业务规则赋值。传统实现方式通常通过手动编码为这些字段赋值,例如在插入或更新操作前,显式调用 setCreateTime(new Date()) 或从上下文中获取操作人信息。然而,这种模式存在明显痛点:
1. 代码冗余:每个涉及公共字段的实体类都需要重复编写赋值逻辑,导致代码臃肿。
2. 维护成本高:若字段规则变更(如时间格式调整、操作人来源切换),需全局搜索并修改所有相关代码。
3. 数据一致性风险:人为遗漏赋值或逻辑错误可能导致字段数据缺失或不准确(例如未刷新 update_time)。
MyBatis-Plus 作为 MyBatis 的增强工具,通过 字段自动填充机制 提供了一种优雅的解决方案。开发者仅需通过简单的注解配置,即可将公共字段的赋值逻辑从业务代码中解耦,由框架在数据操作时自动触发。这种设计不仅减少了冗余代码,还能通过统一规则保障数据准确性,尤其适用于多团队协作或复杂业务场景下的高效开发。 本文将以实际场景为例,解析如何利用 MyBatis-Plus 的 @TableField 注解与 MetaObjectHandler 接口,快速实现字段自动填充,并探讨其底层实现原理与最佳实践。
一、导入依赖
在项目的pom.xml文件中导入必要的依赖:
com.baomidou
mybatis-plus-boot-starter
3.5.3.1
mysql
mysql-connector-java
8.0.33
com.baidu.fsg
uid-generator
二、创建自定义的 MetaObjectHandler
实现类
MetaObjectHandler接口定义了两个主要的方法
insertFill(MetaObject metaObject)
:当执行插入操作时,MyBatis-Plus 会自动调用该方法,你可以在这个方法中为需要自动填充的字段设置值。updateFill(MetaObject metaObject)
:当执行更新操作时,MyBatis-Plus 会自动调用该方法,你可以在这个方法中为需要自动填充的字段设置值。 下面是一个示例,展示如何创建一个自定义的 MetaObjectHandler
实现类,用于自动填充创建时间和更新时间:
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Autowired
private CachedUidGenerator cachedUidGenerator;
@Override
public void insertFill(MetaObject metaObject) {
// 自动填充全局id
if (this.getFieldValByName(BaseEntity.Fields.id, metaObject) == null) {
long id = cachedUidGenerator.getUID();
this.setFieldValByName(BaseEntity.Fields.id, id, metaObject);
}
// 自动填充创建时间
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
// 自动填充更新时间
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
// 自动填充更新时间
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
在上述代码中:
strictInsertFill
方法用于在插入操作时填充字段值,它接收四个参数:MetaObject
对象、字段名、字段类型和要填充的值。strictUpdateFill
方法用于在更新操作时填充字段值,参数与 strictInsertFill
类似。三、在实体类中标记需要自动填充的字段
使用 @TableField
注解的 fill
属性来标记哪些字段需要进行自动填充。示例如下:
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.time.LocalDateTime;
@TableName("your_table_name")
public class YourEntity {
@TableId(type = IdType.INPUT)
private Long id;
private String name;
// 插入时自动填充
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
// 插入和更新时都自动填充
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
// getter 和 setter 方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
}
在上述代码中:
@TableField(fill = FieldFill.INSERT)
表示该字段在插入操作时自动填充。@TableField(fill = FieldFill.INSERT_UPDATE)
表示该字段在插入和更新操作时都自动填充。四、使用 MyBatis-Plus 进行插入和更新操作
在使用 MyBatis-Plus 的 BaseMapper
进行插入和更新操作时,MetaObjectHandler
会自动工作,为标记的字段填充相应的值。示例如下:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface YourEntityMapper extends BaseMapper {
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class YourEntityService {
@Autowired
private YourEntityMapper yourEntityMapper;
public void insertEntity(YourEntity entity) {
yourEntityMapper.insert(entity);
}
public void updateEntity(YourEntity entity) {
yourEntityMapper.updateById(entity);
}
}
五、总结
通过实现 MetaObjectHandler
接口,你可以方便地实现数据库插入和更新操作时的自动填充功能,提高代码的可维护性和开发效率。