关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言
在数据库设计中,常常有一些字段每次都需要赋值,如创建时间、更新时间、操作人、删除标识等。很多时候,为了赶项目匆匆的赋值了一些业务字段,而漏掉了这些字段,导致查询问题的时候,时间点或者操作人对不上,加大了定位问题的难度。
有没有框架级的技术,全局处理这样的统一字段呢?当然有。
Mybatis-Plus
自动填充技术帮我们解决问题。
02 自动填充实现
使用Mybtis-Plus
之前,我们需要简单的搭建环境。
2.1 Mybatis-Plus
简单搭建
Maven
xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
配置
properties
# 数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=root
# 日志实现
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 开启驼峰匹配
mybatis-plus.configuration.map-underscore-to-camel-case=true
# 配置全局数据库主键
mybatis-plus.global-config.db-config.id-type=auto
启动类增加Mapper扫描
@MapperScan("com.simonking.boot.mybaits.mapper")
实体
java
@Data
@TableName("user_info")
public class UserInfo {
/**
* 主键ID
**/
@TableId
private Integer id;
/**
* 姓名
**/
private String name;
/**
* 年龄
**/
private Integer age;
/**
* 性别
**/
private String sex;
/**
* 工作
**/
private String job;
/**
* 生日
**/
private LocalDateTime birthday;
/**
* 创建时间
**/
private LocalDateTime createdTime;
/**
* 更新时间
**/
private LocalDateTime updateTime;
}
继承BaseMapper
java
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}
到这里,Mybatis-Plus
就搭建好了,可以注解注入xxxMapper
调用方法了。
2.2 标记自动填充的字段
在实体类中,你需要使用 @TableField
注解来标记哪些字段需要自动填充,并指定填充的策略。
java
@Data
@TableName("user_info")
public class UserInfo {
// 其他字段...
/**
* 创建时间
**/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdTime;
/**
* 更新时间
**/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
FieldFill
填充的枚举:
java
public enum FieldFill {
DEFAULT, // 默认不处理
INSERT, // 插入填充字段
UPDATE, // 更新填充字段
INSERT_UPDATE // 插入和更新填充字段
}
2.3 实现MetaObjectHandler
创建一个类来实现 MetaObjectHandler
接口,并重写 insertFill
和 updateFill
方法。并确保实现类被Spring
管理,可以通过 @Component
或 @Bean
注解来实现。
java
@Slf4j
@Component
public class AutoFillMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("insertFill 开始自动填充......");
this.strictInsertFill(metaObject, "createdTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("updateFill 开始自动填充......");
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
2.4 测试
java
@Test
void contextLoads01() {
UserInfo userInfo = new UserInfo();
userInfo.setName("test");
userInfo.setAge(18);
userInfoMapper.insert(userInfo);
}

从运行结果来看,cteated_time
和update_time
已经被赋值了。
2.5 思考
这种全局的自动填充有什么问题呢?
先看截图:

这里填充的时候,需要指定字段的名称。但是如果因为开发人员定义错字段,如update_time
-> updated_time
等,这里就需要穷举所有的字段。
有人可能说是开发规范的问题,的确是。但是这种问题确实有点别扭。
能不能通过注解字段指定别名,统一自动赋值的字段呢?官方暂时不支持这种方式。
03 实现原理
自动赋值的的触发机制是如何实现的呢?第一反应,应该是使用了Mybatis
的拦截器插件,细看了之后,并不是。我们一起来看看。
Mybatis-Plus
自动填充调用MetaObjectHandler
,涉及了两个的类:
com.baomidou.mybatisplus.core.MybatisParameterHandler
3.1 MybatisParameterHandler
com.baomidou.mybatisplus.core.MybatisParameterHandler
是对Mybaits
原生的org.apache.ibatis.scripting.defaults.DefaultParameterHandler
的增强。DefaultParameterHandler
是Mybatis
处理SQL
参数的核心类,负责:
- 将
Java
对象转换为JDBC
参数 - 设置
PreparedStatement
的参数值 - 处理类型转换器(
TypeHandler
)
MybatisParameterHandler
自然也就具备了这些功能。构造函数的功能:



我们从源码中可以看到,在创建MybatisParameterHandler
对象的时候,就会根据sqlCommandType
执行insertFill()
还是updateFill()
。
3.2 实例化
我们来看看org.apache.ibatis.executor.parameter.ParameterHandler
是怎么实例化的:



04 小结
上面就是Mybatis-Plus
自动填充的实现和源码分析,下一期,我们将自己通过拦截器或者注解的方式,实现属于我们自己的自动填充的功能。