我们在项目中会用到createBy
、createTime
、updateBy
、updateTime
字段,来记录数据的插入和更新历史。若要实现这些字段的自动填充,MyBatisPlus需要增加一些配置,下面看具体内容吧。
配置
配置需要两步:
- 在字段中增加注解
@TableField(fill = FieldFill.INSERT)
,来表示填写字段,并可声明是在插入时填充,还是在更新时填充
@TableField(fill = FieldFill.INSERT)
private String createBy;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.UPDATE)
private String updateBy;
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
....
FieldFill
检举类原码:
public enum FieldFill {
/**
* 默认不处理
*/
DEFAULT,
/**
* 插入时填充字段
*/
INSERT,
/**
* 更新时填充字段
*/
UPDATE,
/**
* 插入和更新时填充字段
*/
INSERT_UPDATE
}
- 增加
MetaObjectHandler
处理器
在配置类中增加MetaObjectHandler
的实现,并加入到SpringIOC容器中
注意:此处的数据类型要与填充字段数据类型保持一致
/**
* 配置自动填充
*
* @return
*/
@Bean
public MetaObjectHandler metaObjectHandler() {
return new MetaObjectHandler() {
@Override
public void insertFill(MetaObject metaObject) {
// 数据类型要与fileName一致
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
this.strictInsertFill(metaObject, "createBy", String.class, "currentUser");
}
@Override
public void updateFill(MetaObject metaObject) {
// 数据类型要与fileName一致
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
this.strictUpdateFill(metaObject, "updateBy", String.class, "currentUser");
}
};
}
测试代码
插入一条记录
@Test
public void testInsert() {
Dept dept = new Dept();
dept.setName("运维部");
int result = deptMapper.insert(dept);
System.out.println(result);
}
执行日志:
JDBC Connection [HikariProxyConnection@130564501 wrapping com.mysql.cj.jdbc.ConnectionImpl@552ed807] will not be managed by Spring
==> Preparing: INSERT INTO dept ( id, name, deleted, version, create_by, create_time ) VALUES ( ?, ?, ?, ?, ?, ? )
==> Parameters: fd1af5fffc430d515a5f132ab80eeabd(String), 运维部(String), false(Boolean), 0(Integer), currentUser(String), 2020-09-22 10:57:31.089(Timestamp)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@141e879d]
1
通过执行日志我们可以看出,createBy
与createTime
字段已经自动填充上了
更新一条记录
@Test
public void testUpdateById() {
Dept dept = deptMapper.selectById("fd1af5fffc430d515a5f132ab80eeabd");
dept.setName("运维2部");
int result = deptMapper.updateById(dept);
System.out.println(result);
}
执行日志:
JDBC Connection [HikariProxyConnection@577037372 wrapping com.mysql.cj.jdbc.ConnectionImpl@3bec2275] will not be managed by Spring
==> Preparing: SELECT id,name,deleted,version,create_by,create_time,update_by,update_time FROM dept WHERE id=? AND deleted=0
==> Parameters: fd1af5fffc430d515a5f132ab80eeabd(String)
<== Columns: id, name, deleted, version, create_by, create_time, update_by, update_time
<== Row: fd1af5fffc430d515a5f132ab80eeabd, 运维部, 0, 0, currentUser, 2020-09-22 10:57:31, null, null
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@141e879d]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@299270eb] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@1966114624 wrapping com.mysql.cj.jdbc.ConnectionImpl@3bec2275] will not be managed by Spring
==> Preparing: UPDATE dept SET name=?, version=?, create_by=?, create_time=?, update_by=?, update_time=? WHERE id=? AND version=? AND deleted=0
==> Parameters: 运维2部(String), 1(Integer), currentUser(String), 2020-09-22 10:57:31.0(Timestamp), currentUser(String), 2020-09-22 11:00:06.151(Timestamp), fd1af5fffc430d515a5f132ab80eeabd(String), 0(Integer)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@299270eb]
1
从日志中可以看出,updateBy
和updateTime
字段已自动 填充上
注意事项
- 填充原理是直接给
entity
的属性设置值!!! - 注解则是指定该属性在对应情况下必有值,如果无值则入库会是
null
MetaObjectHandler
提供的默认方法的策略均为:如果属性有值则不覆盖,如果填充值为null
则不填充- 字段必须声明
TableField
注解,属性fill
选择对应策略,该声明告知Mybatis-Plus
需要预留注入SQL
字段 - 填充处理器
MyMetaObjectHandler
在 Spring Boot 中需要声明@Component
或@Bean
注入 - 要想根据注解
FieldFill.xxx
和字段名
以及字段类型
来区分必须使用父类的strictInsertFill
或者strictUpdateFill
方法 - 不需要根据任何来区分可以使用父类的
fillStrategy
方法