//这是公共父类包含创建时间,创建人等信息
@JsonIgnoreProperties({"transMap"})
public abstract class BaseDO implements Serializable, TransPojo {
@TableField(
fill = FieldFill.INSERT//核心表示该字段是在添加时设置
)
private LocalDateTime createTime;
@TableField(
fill = FieldFill.INSERT_UPDATE//表示该字段在添加更新时设置
)
private LocalDateTime updateTime;
@TableField(
fill = FieldFill.INSERT//表示字段在添加时设置
)
private String creator;
@TableField(
fill = FieldFill.INSERT_UPDATE,//表示该字段在添加更新时设置
)
private String updater;
@TableLogic
private Boolean deleted;
}
//这是实体类继承了BaseDO当然该实体类对应的数据表有创建时间这些字段
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MaterialCategoryDO extends BaseDO {
/**
* 主键ID
*/
@TableId(type = IdType.ASSIGN_ID)
private Long materialCategoryId;
/**
* 物品分类ID
*/
private Long parentId;
/**
* 物品分类名称
*/
*/
}
materialCategoryMapper.insert(materialCategory);//service层直接调用就行
除此之外还要写个拦截器,通过拦截器拦截并设置创建时间等字段
这里并没有写@Component注解注入到 Spring 容器,因为在其他地方配置过了
@Configuration
public class MybatisPlusConfig {
// 手动注册处理器
@Bean
public MetaObjectHandler metaObjectHandler() {
return new DefaultDBFieldHandler();
}
}
public class DefaultDBFieldHandler implements MetaObjectHandler {//这里需要继承这个接口原因后面会讲
@Override
public void insertFill(MetaObject metaObject) {
if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();
Date current = new Date();
// 创建时间为空,则以当前时间为插入时间
if (Objects.isNull(baseDO.getCreateTime())) {
baseDO.setCreateTime(current);
}
// 更新时间为空,则以当前时间为更新时间
if (Objects.isNull(baseDO.getUpdateTime())) {
baseDO.setUpdateTime(current);
}
String userId = ..... 这里自定义实现逻辑,获取当前登录用户
// 当前登录用户不为空,创建人为空,则当前登录用户为创建人
if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) {
baseDO.setCreator(userId.toString());
}
// 当前登录用户不为空,更新人为空,则当前登录用户为更新人
if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
baseDO.setUpdater(userId.toString());
}
}
}
@Override
public void updateFill(MetaObject metaObject) {
// 更新时间为空,则以当前时间为更新时间
Object modifyTime = getFieldValByName("updateTime", metaObject);
if (Objects.isNull(modifyTime)) {
setFieldValByName("updateTime", new Date(), metaObject);
}
// 当前登录用户不为空,更新人为空,则当前登录用户为更新人
Object modifier = getFieldValByName("updater", metaObject);
String userId = ..... 这里自定义实现逻辑,获取当前登录用户
if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
setFieldValByName("updater", userId.toString(), metaObject);
}
}
}
核心就是mybatis-plus能够自动检测@TableField(fill=...)注解,然后通过拦截器来设置创建时间等字段
具体的调用过程图如下
可以看到这里的BaseDO声明为抽象类
-
设计意图:
BaseDO
仅作为基础模板存在,包含所有实体共有的审计字段 -
强制约束:要求开发者必须创建具体子类(如
MaterialCategoryDO
)才能使用 -
类比现实:类似"动物"抽象类,必须通过"猫"/"狗"等具体子类实例化
注意到这里继承了MetaObjectHandler
因为 MyBatis Plus 通过接口类型识别处理器所以需要继承这个接口
核心代码
// MyBatis Plus 的填充处理器接口
public interface MetaObjectHandler {
void insertFill(MetaObject metaObject); // 插入操作时触发
void updateFill(MetaObject metaObject); // 更新操作时触发
}