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 统一管理创建人更新人创建时间更新时间等公共字段的主要内容,如果未能解决你的问题,请参考以下文章

mybatisplus自动填充

springboot简单使用mybatisplus

springboot简单使用mybatisplus

创建统一的依赖管理

SpringBoot整合MyBatisPlus配置动态数据源

AOP统一处理修改人创建人修改时间创建时间