Mybatis plus 3.x 公用字段 全局字段填充配置 Spring Boot

文章用到的技术框架版本如下:

Mybatis Plus 3.3.2

Spring Boot 2.3.2.RELEASE

MySQL 8.0

设计背景

在设计表结构的时候,往往会有一些公用的字段,如创建人编号(create_user_id),最后修改人编号(last_update_user_id)、创建时间(create_time)、最后修改时间(last_update_time)等。

表结构

create table sys_user
(
    user_id        varchar(36)   not null comment '用户编号',
    user_name      varchar(36)   not null comment '用户名称',
    password       varchar(30)   not null comment '密码(demo项目,明文录入)',
    status         int default 1 not null comment '状态(0:禁用,1:启用)',
    create_time    datetime      null comment '创建时间',
    update_time    datetime      null comment '修改时间',
    create_user_id varchar(36)   null comment '创建人编号',
    update_user_id varchar(36)   null comment '修改人编号',
    primary key(user_id)
) comment '用户数据表';

在以往的项目开发的过程中,对上述字段的录入方式差不多都是这样的set方法:

//录入创建时间
sysUser.setCreateTime(new Date());
//录入创建人
sysUser.setCreateUserId(ShiroUtils.getUserId());
//other code .....

开发进度逐渐推进后,某天查看数据时出现了下方的情况:

等等!!修改人和修改时间怎么没了???看看代码:

/*
前台数据: 
{
    userId:'a15b6c54-e137-11ea-97ee-0242ac110002',
    password:'xxx'
}
*/

/**
*    修改用户数据
*    @param sysUser 用户数据
*/
public void updateUserData(SysUser sysUser){

    this.baseMapper.updateById(sysUser);

}

直接入库了,没有对updateTime、updateUser字段做更新...

解决方案

方案描述

针对上述这样的情况,我们可以通过自定义Mybatis-plus提供的元对象字段填充控制器抽象类,实现公共字段自动写入。

废话不多说,直接上类:

元对象字段填充控制器抽象类

package com.qianlingo.mybatisplushandlerdemo.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Configuration;

/**
 * MetaObjectHandler
 * <p>
 * 官方注释:
 * 元对象字段填充控制器抽象类,实现公共字段自动写入
 * 所有入参的 MetaObject 必定是 entity 或其子类的 MetaObject
 * </p>
 * @author qianlingo
 * @date 2020/8/18
 */
@Configuration
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 插入元对象字段填充(用于插入时对公共字段的填充)
     * 需字段加入
     * 注解: TableField(fill = FieldFill.INSERT)
     * or
     * 注解: TableField(fill = FieldFill.INSERT_UPDATE)
     * @param metaObject 元对象
     */
    @Override
    public void insertFill(MetaObject metaObject) {

    }

    /**
     * 更新元对象字段填充(用于更新时对公共字段的填充)
     * 需字段加入
     * 注解: TableField(fill = FieldFill.UPDATE)
     * or
     * 注解: TableField(fill = FieldFill.INSERT_UPDATE)
     * @param metaObject 元对象
     */
    @Override
    public void updateFill(MetaObject metaObject) {

    }
}

我使用的是较新的3.3.2版本Mybatis-Plus,MetaObjectHandler类是通过实现进行自定义的,翻看了很多博文都是通过继承的,应该版本不同自定义的方式不同,大家可留意一下。

方法讲解

insertFill方法

在实体类字段顶上加入fii属性为INSERT或INSERT_UPDATE的@TableField注解后,进行数据库操作时会进入该方法。

    /**
     * 创建者
     */
    @ApiModelProperty(value = "创建者")
    @TableField(fill = FieldFill.INSERT)
    private String createUserId;

updateFill方法

在实体类字段顶上加入fii属性为UPDATE或INSERT_UPDATE的@TableField注解后,进行数据库操作时会进入该方法。

对@TableField(fill=XXX)注解的全局配置,后面会花时间分Mybatis-plus不同版本进行讲解,本文不做过多展开。

    /**
     * 更新者
     */
    @ApiModelProperty(value = "更新者")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateUserId;

OK,接下来我们对两个方法具体的业务代码进行编写!

首先是insertFill方法:

/**
     * 插入元对象字段填充(用于插入时对公共字段的填充)
     * 需字段加入
     * 注解: TableField(fill = FieldFill.INSERT)
     * or
     * 注解: TableField(fill = FieldFill.INSERT_UPDATE)
     * @param metaObject 元对象
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        //填充create_time字段公用数据
        if (metaObject.hasGetter("createTime") && metaObject.hasGetter("createTime")) {
            setFieldValByName("createTime", new Date(), metaObject);
        }
        //填充 createUserId 字段公用数据
        if (metaObject.hasGetter("createUserId") && metaObject.hasGetter("createUserId")) {
            setFieldValByName("createUserId", ADMIN_USER_ID, metaObject);
        }
        //填充 updateTime 字段公用数据
        if (metaObject.hasGetter("updateTime") && metaObject.hasGetter("updateTime")) {
            setFieldValByName("updateTime", new Date(), metaObject);
        }
        //填充 updateUserId 字段公用数据
        if (metaObject.hasGetter("updateUserId") && metaObject.hasGetter("updateUserId")) {
            setFieldValByName("updateUserId", ADMIN_USER_ID, metaObject);
        }
    }

metaObject.hasGetter(String name) 方法:  返回boolean类型数据,判断传入的实体类是否有该属性(实体类中的属性名)的get方法。

setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) 方法:对某个属性(实体类中的属性名)赋值。

核心方法就是上述两行啦,insertFill方法的作用,是在做新增操作时将新增、修改人和时间都做填充。

理解上述后,updateFill方法就显得很简单了,即只在做修改操作时将修改人和时间做填充即可。

 /**
     * 更新元对象字段填充(用于更新时对公共字段的填充)
     * 需字段加入
     * 注解: TableField(fill = FieldFill.UPDATE)
     * or
     * 注解: TableField(fill = FieldFill.INSERT_UPDATE)
     * @param metaObject 元对象
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        //填充 updateTime 字段公用数据
        if (metaObject.hasGetter("updateTime") && metaObject.hasGetter("updateTime")) {
            setFieldValByName("updateTime", new Date(), metaObject);
        }
        //填充 updateUserId 字段公用数据
        if (metaObject.hasGetter("updateUserId") && metaObject.hasGetter("updateUserId")) {
            setFieldValByName("updateUserId", ADMIN_USER_ID, metaObject);
        }
    }

编写测试类

package com.qianlingo.mybatisplushandlerdemo;
import java.util.UUID;

import com.qianlingo.mybatisplushandlerdemo.mybatis.domain.sys.SysUser;
import com.qianlingo.mybatisplushandlerdemo.service.sys.ISysUserService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

/**
 * 用户测试类
 *
 * @author qianlingo
 * @date 2020/8/18
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = MybatisPlusHandlerDemoApplication.class)
public class SysUserTest {

    @Resource
    private ISysUserService iSysUserService;

    @Test
    public void addTest(){
        //组装数据
        SysUser sysUser = new SysUser();
        String userId = UUID.randomUUID().toString();
        System.out.println("userId:"+userId);
        sysUser.setUserId(userId);
        sysUser.setUserName("user"+UUID.randomUUID().toString().substring(0,10));
        sysUser.setPassword("qianlingo");
        sysUser.setStatus(1);
        this.iSysUserService.save(sysUser);
        getUserData();
    }

    @Test
    public void updateTest(){
        //组装数据
        SysUser sysUser = this.iSysUserService.getById("");
        sysUser.setPassword("qianlingooo");
        this.iSysUserService.updateById(sysUser);
        getUserData();
    }

    private void getUserData(){
        SysUser sysUser = this.iSysUserService.getById("");
        System.out.println(sysUser);
    }
}

分别执行addTest、updateTest方法,可查看到数据变化:

2020-08-18 18:44:58.918  INFO 3819 --- [           main] c.q.mybatisplushandlerdemo.SysUserTest   :  开始执行 addTest 方法
userId:c32ad96f-ff9f-4642-968c-89ef0a6fa4e0
2020-08-18 18:44:58.994  INFO 3819 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2020-08-18 18:44:59.280  INFO 3819 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2020-08-18 18:44:59.291 DEBUG 3819 --- [           main] c.q.m.m.mapper.sys.SysUserMapper.insert  : ==>  Preparing: INSERT INTO sys_user ( user_id, user_name, password, status, create_time, update_time, create_user_id, update_user_id ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? ) 
2020-08-18 18:44:59.360 DEBUG 3819 --- [           main] c.q.m.m.mapper.sys.SysUserMapper.insert  : ==> Parameters: c32ad96f-ff9f-4642-968c-89ef0a6fa4e0(String), user4d0f44a5-8(String), qianlingo(String), 1(Integer), 2020-08-18 18:44:58.989(Timestamp), 2020-08-18 18:44:58.989(Timestamp), a15b6c54-e137-11ea-97ee-0242ac110002(String), a15b6c54-e137-11ea-97ee-0242ac110002(String)
2020-08-18 18:44:59.374 DEBUG 3819 --- [           main] c.q.m.m.mapper.sys.SysUserMapper.insert  : <==    Updates: 1
2020-08-18 18:44:59.429 DEBUG 3819 --- [           main] c.q.m.m.m.sys.SysUserMapper.selectById   : ==>  Preparing: SELECT user_id,user_name,password,status,create_time,update_time,create_user_id,update_user_id FROM sys_user WHERE user_id=? 
2020-08-18 18:44:59.448 DEBUG 3819 --- [           main] c.q.m.m.m.sys.SysUserMapper.selectById   : ==> Parameters: c32ad96f-ff9f-4642-968c-89ef0a6fa4e0(String)
2020-08-18 18:44:59.743 DEBUG 3819 --- [           main] c.q.m.m.m.sys.SysUserMapper.selectById   : <==      Total: 1
SysUser(userId=c32ad96f-ff9f-4642-968c-89ef0a6fa4e0, userName=user4d0f44a5-8, password=qianlingo, status=1, createTime=Tue Aug 18 18:44:59 CST 2020, updateTime=Tue Aug 18 18:44:59 CST 2020, createUserId=a15b6c54-e137-11ea-97ee-0242ac110002, updateUserId=a15b6c54-e137-11ea-97ee-0242ac110002)
2020-08-18 18:45:50.038  INFO 3824 --- [           main] c.q.mybatisplushandlerdemo.SysUserTest   :  开始执行 updateTest 方法
2020-08-18 18:45:50.090  INFO 3824 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2020-08-18 18:45:50.383  INFO 3824 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2020-08-18 18:45:50.402 DEBUG 3824 --- [           main] c.q.m.m.m.sys.SysUserMapper.selectById   : ==>  Preparing: SELECT user_id,user_name,password,status,create_time,update_time,create_user_id,update_user_id FROM sys_user WHERE user_id=? 
2020-08-18 18:45:50.444 DEBUG 3824 --- [           main] c.q.m.m.m.sys.SysUserMapper.selectById   : ==> Parameters: c32ad96f-ff9f-4642-968c-89ef0a6fa4e0(String)
2020-08-18 18:45:50.470 DEBUG 3824 --- [           main] c.q.m.m.m.sys.SysUserMapper.selectById   : <==      Total: 1
2020-08-18 18:45:50.612 DEBUG 3824 --- [           main] c.q.m.m.m.sys.SysUserMapper.updateById   : ==>  Preparing: UPDATE sys_user SET user_name=?, password=?, status=?, create_time=?, update_time=?, create_user_id=?, update_user_id=? WHERE user_id=? 
2020-08-18 18:45:50.629 DEBUG 3824 --- [           main] c.q.m.m.m.sys.SysUserMapper.updateById   : ==> Parameters: user4d0f44a5-8(String), qianlingooo(String), 1(Integer), 2020-08-18 18:44:59.0(Timestamp), 2020-08-18 18:45:50.611(Timestamp), a15b6c54-e137-11ea-97ee-0242ac110002(String), a15b6c54-e137-11ea-97ee-0242ac110002(String), c32ad96f-ff9f-4642-968c-89ef0a6fa4e0(String)
2020-08-18 18:45:50.636 DEBUG 3824 --- [           main] c.q.m.m.m.sys.SysUserMapper.updateById   : <==    Updates: 1
2020-08-18 18:45:50.637 DEBUG 3824 --- [           main] c.q.m.m.m.sys.SysUserMapper.selectById   : ==>  Preparing: SELECT user_id,user_name,password,status,create_time,update_time,create_user_id,update_user_id FROM sys_user WHERE user_id=? 
2020-08-18 18:45:50.637 DEBUG 3824 --- [           main] c.q.m.m.m.sys.SysUserMapper.selectById   : ==> Parameters: c32ad96f-ff9f-4642-968c-89ef0a6fa4e0(String)
2020-08-18 18:45:50.640 DEBUG 3824 --- [           main] c.q.m.m.m.sys.SysUserMapper.selectById   : <==      Total: 1
SysUser(userId=c32ad96f-ff9f-4642-968c-89ef0a6fa4e0, userName=user4d0f44a5-8, password=qianlingooo, status=1, createTime=Tue Aug 18 18:44:59 CST 2020, updateTime=Tue Aug 18 18:45:51 CST 2020, createUserId=a15b6c54-e137-11ea-97ee-0242ac110002, updateUserId=a15b6c54-e137-11ea-97ee-0242ac110002)

create_time、update_time、create_user_id、update_user_id四个字段均按需求自动填充了!

结尾

文章的相关代码已同步上传至Github和Gitee了,如果对文章有不清楚的地方何不看看代码?:)

GitHub: https://github.com/qianlingo/mybatis-plus-handler-demo

Gitee: https://gitee.com/qianlingooo/mybatis-plus-handler-demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值