MybatisPlus 统一管理创建人更新人创建时间更新时间等公共字段
Posted 明湖起风了
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MybatisPlus 统一管理创建人更新人创建时间更新时间等公共字段相关的知识,希望对你有一定的参考价值。
开发过程中的问题
1. 在设计数据库模型的时候,我们通常会在表中创建创建人、创建时间、更新人、更新时间等通用的字段来记录每行数据的创建和变动信息。比如在 inset 和 update 过程方法中要不停的set的创建时间字段或更新时间字段等公共信息。
2. 并且,如果有大量的表,每个表都有这些公共字段,不论是在创建或者更新的时候都是重复繁琐的操作,让人难受。
针对问题1,我们可以通过代码自动生成创建人、更新人、创建时间、更新时间等公共字段的信息,来减少开发者的工作量(大量使用set方法)。
针对问题2,我们可以将大量表中的重复的公共字段抽取出来,做一个通用字段的bean类型,在java中让它成为父类,让其他表继承。
实现:
1. 抽取公共字段创建父类基础模型
例如,有 im_base_entity 表,表中有些字段与其他表中字段一致(主要根据实际业务区分):创建人、更新人、创建时间、更新时间、逻辑删除
CREATE TABLE `im_base_entity` (
`id` int(11) NOT NULL COMMENT '主键',
`username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
`password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`creator` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建者',
`updater` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新者',
`deleted` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '逻辑删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
将重复字段抽取,并创建java的父类基础模型
package org.example.bean;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 数据库模型设计时抽出所有通用字段,抽象为父类
*/
@Data
public abstract class BaseEntity implements Serializable
/**
* 创建时间
* 意思是新建的时候插入
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 最后更新时间
* 意思是新建和修改的时候插入
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/**
* 创建者,目前使用 SysUser 的 id 编号
* 意思是新建的时候插入
* 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。
*/
@TableField(fill = FieldFill.INSERT)
private String creator;
/**
* 更新者,目前使用 SysUser 的 id 编号
* 意思是新建和修改的时候插入
* 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updater;
/**
* 是否删除
* 框架提供的逻辑删除注解。如果使用delete关键字,会报错
* 如果进行查询,会过滤被逻辑删除的字段!
* 0 未删除
* 1 已删除
*/
@TableLogic
private Boolean deleted;
2. java中所有业务实体继承该父类基础模型
注意:这里继承了父类 BaseEntity,所以可以不用在创建公共字段的声明了。但是在数据库表中公共字段还是要有的。
package org.example.bean;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* autoResultMap = true
* 如果数据库是json类型的字段,同时autoResultMap=true,
* 那么在select的时候,数据库json字段对应的实体类字段可以直接映射,
* 该字段类型可以是某个类,也可以是List。
*
* @EqualsAndHashCode(callSuper = true)
* 该注解用于子类对象之间进行比较的时候,如果不加这个注解,当创建俩个 MyTableEntity 对象时,
* 这俩个对象比较是相等的,即使给这俩个对象设置了不同的值。
*
* @Builder
* 为你的类生成相对略微复杂的构建器API。
* 可以让你以下面显示的那样调用你的代码,来初始化你的实例对象:
* MyTableEntity.builder()
* .id( "001" )
* .password( "110" )
* .build();
*/
@TableName(value = "im_base_entity", autoResultMap = true)
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MyTableEntity extends BaseEntity
/**
* 用户ID
*/
@TableId
private Long id;
/**
* 用户账号
*/
private String username;
/**
* 加密后的密码
*/
private String password;
3. 实现 MetaObjectHandler 接口,(元对象字段填充控制器抽象类),实现公共字段自动写入功能
package org.example.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.log4j.Log4j;
import org.apache.ibatis.reflection.MetaObject;
import org.example.bean.LoginUser;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Objects;
/**
* 如果没有显式的对通用参数进行赋值,这里会对通用参数进行填充、赋值
*/
@Log4j
@Component
public class DefaultDBFieldHandler implements MetaObjectHandler
@Override
public void insertFill(MetaObject metaObject)
// 可以通过 getFieldValByName()方法判断
// Object modifyTime = getFieldValByName("updateTime", metaObject);
log.info("进入创建");
// 获取当前用户信息
LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("creator",loginUser.getUser().getUserName(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
this.setFieldValByName("updater",loginUser.getUser().getUserName(),metaObject);
@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);
LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String userId = loginUser.getUser().getUserName();
if (Objects.nonNull(userId) && Objects.isNull(modifier))
setFieldValByName("updater", userId.toString(), metaObject);
注意:
使用 @TableLogic 注解后,如果使用delete关键字,会报错 ,如果进行查询,会过滤被逻辑删除的字段。但是需要在yml中配置
mybatis-plus:
configuration:
#开启驼峰命名
map-underscore-to-camel-case: true
mapper-locations: classpath*:/mapper/*.xml
global-config:
db-config:
logic-delete-field: flag #全局逻辑删除字段值 3.3.0开始支持,详情看下面。
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
配置完成后,添加业务,创建和更新 im_base_entity 表,进行测试,自动添加了。
至此完毕。
MybatisPlus的自动填充功能使用!
有时我们希望在更新数据的时候,自动完成某些字段的值的填充,如创建一个实体的时候,自动生成创建时间,更新的时候自动改变更新时间等。
- 在指定字段标注注解,生成器策略部分也可以配置。
// 创建时间
@TableField(fill = FieldFill.INSERT)
private Date createTime;
// 更新时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
public enum FieldFill {
/**
* 默认不处理
*/
DEFAULT,
/**
* 插入填充字段
*/
INSERT,
/**
* 更新填充字段
*/
UPDATE,
/**
* 插入和更新填充字段
*/
INSERT_UPDATE
}
- 实现元对象处理接口:
com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
// fieldName 指的是实体类的属性名,而不是数据库的字段名
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.strictInsertFill(
metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(
metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(
// 起始版本 3.3.0(推荐)
metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
// 或者
this.strictUpdateFill(
// 起始版本 3.3.3(推荐)
metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
}
}
以上是关于MybatisPlus 统一管理创建人更新人创建时间更新时间等公共字段的主要内容,如果未能解决你的问题,请参考以下文章