使用场景

MetaObjectHandler是元对象字段填充控制器抽象类,实现公共字段自动写入。

比如通常,我们在建表时,会设置几个公共字段:创建人(creator)、更新人(uptater)、创建时间(create_time)、更新时间(update_time)。

每次将实体对象新增入库时,都要设置创建人和创建时间;每次更新实体对象时,都要设置更新人和更新时间;如果这是都放在业务代码中,很是繁琐,那么可不可以统一配置,自动帮我们添加这些属性呢?答案就是使用MetaObjectHandler。

使用姿势

官方说明:https://baomidou.com/pages/4c6bcf/

注意:不同版本api略有不同,但是步骤是一样的,接口也是一样的,本文是3.1.0 。

步骤如下:

实现MetaObjectHandler接口

MetaObjectHandler接口有两个接口方法,需要我们自己去实现它:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 插入元对象字段填充(用于插入时对公共字段的填充)
*
* @param metaObject 元对象
*/
void insertFill(MetaObject metaObject);

/**
* 更新元对象字段填充(用于更新时对公共字段的填充)
*
* @param metaObject 元对象
*/
void updateFill(MetaObject metaObject);

自定义实现类MyMetaObjectHandler如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.setFieldValByName("creator", bucUserBo.getEmpId(), metaObject);
this.setFieldValByName("create_time", new Date(), metaObject);
}

@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.setFieldValByName("updater", "", metaObject);
this.setFieldValByName("update_time", new Date(), metaObject);
}
}

实体类上添加注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 创建时间
*/
@TableField(value = "create_time",fill = FieldFill.INSERT)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;

/**
* 创建者工号
*/
@TableField(value = "creator",fill = FieldFill.INSERT)
private String creator;

/**
* 更新时间
*/
@TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;

/**
* 更新者工号
*/
@TableField(value = "updater",fill = FieldFill.INSERT_UPDATE)
private String updater;

其中,FieldFill枚举有4个属性

DEFAULT :默认不处理
INSERT : 插入操作时进行填充字段
UPDATE :更新操作时填充字段
INSERT_UPDATE :插入和更新操作时填充字段

不生效的场景

使用mapper.xml的sql不生效

必须使用mybatis的api进行插入和更新操作。

boolean update(Wrapper updateWrapper) 不生效

不生效方式:

1
this.update(new UpdateWrapper<User>().set("name", "张三")));

生效方式:

1
this.update(new User(), new UpdateWrapper<User>().set("name", "张三")));

@TableField注解要加上

@TableField(value = “update_time”, fill = FieldFill.UPDATE)
实现接口后,此注解也要加,并且指定fill参数值,不然不会填充。

其他

如果属性有值则不覆盖,如果sql中赋值了,自动填充又设置为其他值,则已sql中的值为准‘
如果填充值为null则不填充;比如this.setFieldValByName(“update_time”, null, metaObject); 实际是不会更新为null的;

3.1.0版本的中的更新时间不生效,可以升级为3.3.0版本,然后使用如下方式:

1
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());