Springboot +mybatis-plus 实现公共字段自动填充

一、应用场景

平时在建数据表的时候都会有创建时间、创建者、修改时间和修改者这四个字段,对于这些大部分表都有的字段,每次在新增和修改的时候都要考虑到这几个字段有没有传进去,很麻烦。mybatisPlus有一个很好的解决方案。也就是公共字段自动填充的功能。

一般满足下面条件的字段就可以使用此功能:
(1)这个字段是大部分表都会有的;
(2)这个字段的值是固定的,或则字段值是可以在后台动态获取的。

阿里巴巴开发手册中也有这样的提示,如果对于这些公共字段可以进行统一处理,不需要每次进行插入或者更新操作的时候 set 一下,就可以提高开发效率,解放双手。

自动填充功能的主要使用步骤:
(1)新建一个表t_user增加create_time(创建时间)、create_user(创建者)、update_time(修改时间)、update_user(修改者) 等字段。
(2)需要在填充的公共字段上面添加@TableField注解
(3)自定义实现类 MyMetaObjectHandler,重写insertFill、updateFill方法 方法中设置created_time、updated_time等的值

二、代码实现步骤

1.建数据库表 t_user

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `name` varchar(255) DEFAULT NULL COMMENT '名称',
  `age` int(10) DEFAULT NULL COMMENT '年龄',
  `remarks` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_user` varchar(255) DEFAULT NULL COMMENT '创建人',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `update_user` varchar(255) DEFAULT NULL COMMENT '更新人',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户信息表';


2.创建spring boot项目集成mybatis-plus实现字段自动填充

2.1 配置pom.xml 和 application.yml

pom.xml配置如下:

 <!--web-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-test</artifactId>
     <scope>test</scope>
 </dependency>

 <!--热部署-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-devtools</artifactId>
     <scope>runtime</scope>
     <optional>true</optional>
 </dependency>
 <!--lombok-->
 <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <optional>true</optional>
 </dependency>
 <!--mybatis-plus自动的维护了mybatis以及mybatis-spring的依赖,
 在springboot中这三者不能同时的出现,避免版本的冲突,表示:跳进过这个坑-->
 <!--mybatis-plus-->
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.4.3</version>
 </dependency>
 <!--mysql驱动-->
 <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <scope>runtime</scope>
 </dependency>
 <!-- alibaba的druid数据库连接池 -->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid</artifactId>
     <version>1.1.20</version>
 </dependency>

 <!-- alibaba的druid数据库连接池 -->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid-spring-boot-starter</artifactId>
     <version>1.1.20</version>
 </dependency>

application.yml


# 服务端口
server:
  port: 8083

# 数据源配置
spring:
  datasource:
    name: test
    url: jdbc:mysql://localhost:3306/db_user?&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSl=false
    username: root
    password:
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

    ## 配置连接池信息
    ## 初始化大小,最小,最大
    initialSize: 5
    minIdle: 5
    maxActive: 30
    ## 配置获取连接等待超时的时间
    maxWait: 60000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall
    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

    # 超过时间限制是否回收
    removeAbandoned: true
    # 超时时间;单位为秒。180秒=3分钟
    removeAbandonedTimeout: 180
    # 关闭abanded连接时输出错误日志
    logAbandoned: true

# mybatis-plus 默认扫描mapper.xml的目录
mybatis-plus:
  mapper-locations: classpath*:/mapper/*.xml
  #配置sql打印日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl



2.2 编写User实体,添加填充注解

创建一个实体类,然后在需要自动填充的属性上加注解 @TableField(fill = FieldFill.INSERT)、@TableField(fill = FieldFill.INSERT_UPDATE) 等注解。



import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;


@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_user")
public class User implements Serializable {

    private  static final long serialVersionUID = 1L;

    /**
     * 用户id
     */
    @TableId(value="id", type = IdType.AUTO)
    private Integer id;
    /**
     * 名称
     */
    @TableField("name")
    private String name;

    /**
     * 年龄
     */
    @TableField("age")
    private Integer age;

    /**
     * 备注
     */
    @TableField("remarks")
    private String remarks;

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

    /**
     * 创建时间
     */
    @TableField(value = "create_time", fill = FieldFill.INSERT)

    private Date create_time;

    /**
     * 修改时间
     */
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    private Date update_time;

    /**
     * 修改者id
     */
    @TableField(value = "update_user", fill = FieldFill.INSERT_UPDATE)
    private String update_user;
}


其中 fill 属性为字段自动填充策略

在这里插入图片描述

2.3 创建一个UserMapper

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.autofilldemo.entity.User;
import org.springframework.stereotype.Repository;


@Repository
public interface UserMapper extends BaseMapper<User> {
}


2.4 自定义公共字段填充处理器

创建自定义实现类MyMetaObjectHandler 实现 MetaObjectHandler 接口,重写insertFill和updateFill方法

注意:
MyBatis Plus 版本不同,实现方式可能会有些许不同,在 3.3.0以上版本是实现 MetaObjectHandler接口,低版本可能是继承 MetaObjectHandler 抽象类,来实现对应的方法。

下面为实现插入和更新数据的字段填充逻辑,在插入对象时,对创建时间 create_time和修改时间 update_time自动填充为当前时间,创建者update_user、修改者update_user字段自动填充为当前用户id,在更新对象时,将修改时间 update_time修改为最新时间,修改者为当前用户id。



import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;

/**
 * 配置mybatis-plus自动填充类

 */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    /**
     * 插入填充
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ......");

        this.fillStrategy(metaObject,"create_time", new Date());
        this.fillStrategy(metaObject,"update_time", new Date());

        this.setFieldValByName("create_user",getCurrentUserId(),metaObject);
        this.setFieldValByName("update_user",getCurrentUserId(),metaObject);

        log.info("end insert fill ......");
    }

    /**
     * 修改填充
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ......");
        this.fillStrategy(metaObject,"update_time", new Date());
        this.fillStrategy(metaObject,"update_user", getCurrentUserId());

        log.info("end update fill ......");
    }

    /**
     * 获取当前用户id
     * @return
     */
    private String getCurrentUserId() {
        return "1";
    }
}


其中,默认填充策略为默认有值不覆盖,如果提供的值为 null 也不填充。

2.5 创建UserController,编写方法测试字段自动填充

编写用户添加和编辑方法,检验是否在插入和更新操作时,是否会自动填充响应的字段。



import com.example.autofilldemo.dao.UserMapper;
import com.example.autofilldemo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;


@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserMapper userMapper;

    /**
     * 添加用户信息
     */
    @PostMapping("add")
    public Map<String,Object> addProduct(@RequestBody User user){
        Map<String,Object> result = new HashMap<>();
        int n = userMapper.insert(user);
        if(n>0){
            result.put("code","200");
            result.put("id",user.getId());
        }else{
            result.put("code","400");
            result.put("msg","添加用户失败");
        }
        return result;
    }

    /**
     * 编辑商品信息
     */
    @PostMapping("update")
    public Map<String,Object> updateProduct(@RequestBody User user){
        Map<String,Object> result = new HashMap<>();
        int n = userMapper.updateById(user);
        if(n>0){
            result.put("code","200");
        }else{
            result.put("code","400");
            result.put("msg","编辑用户失败");
        }
        return result;
    }
}


三、测试

启动项目,借助postman工具,测试:
(1)添加一个用户信息到数据库,可以看到并没有设置create_time、update_time、create_user和update_user,但程序会自动填充到数据库:

四、扩展

1.编写BaseEntity公共字段封装类
另外,可以将公共字段封装到公共类中,比如BaseEntity,其他的实体类可以继承这个公共类,达到代码复用,减少冗余的效果:



import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;

import java.util.Date;

/**
 * 公共字段
 * @author qzz
 */
@Data
public class BaseEntity {

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

    /**
     * 创建时间
     */
    @TableField(value = "create_time", fill = FieldFill.INSERT)

    private Date create_time;

    /**
     * 修改时间
     */
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    private Date update_time;

    /**
     * 修改者id
     */
    @TableField(value = "update_user", fill = FieldFill.INSERT_UPDATE)
    private String update_user;
}


2.修改User实体类



import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;


@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_user")
public class User extends BaseEntity implements Serializable{

    private  static final long serialVersionUID = 1L;

    /**
     * 用户id
     */
    @TableId(value="id", type = IdType.AUTO)
    private Integer id;
    /**
     * 名称
     */
    @TableField("name")
    private String name;

    /**
     * 年龄
     */
    @TableField("age")
    private Integer age;

    /**
     * 备注
     */
    @TableField("remarks")
    private String remarks;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值