| @Author:TTODS

前言

MyBatisPlus提供了非常好用的字段填充功能,可以在插入记录或更新记录的时候,根据设定的规则为字段填充指定的值。本文将演示如何使用MybatisPlus的字段填充功能,自动填充表中记录的更新时间字段及插入时间字段。

新建一个测试表record

在数据库中新建一个record表,该表一共有四个字段:

  1. id 编号
  2. record_name 记录名
  3. create_date 插入日期
  4. update_date 修改日期
CREATE TABLE `record`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `record_name` varchar(255) COMMENT '记录名',
  `create_date` timestamp(0) COMMENT '创建时间',
  `update_date` timestamp(0) COMMENT '更新时间',
  PRIMARY KEY (`id`)
);

创建好的表结构如下:

mybatis 增加javaType mybatis添加字段_mybatis 增加javaType

编写实体类Record

com.example.pojo包中创建record表对应的实体类Record

package com.example.pojo;

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

import java.time.LocalDateTime;

@Data
public class Record {
    @TableId(type = IdType.AUTO)
    private Integer id;
    @TableField(value="record_name")
    private String name;
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateDate;
}

在实体类中我们使用到了一些注解:

  • @TableId注解,标注的属性对应的字段为表的主键,其中的参数type=IdType.AUTO表示主键为自增
  • @TableField注解,标注的属性为数据库的一个字段,value属性表示对应的数据库表中的字段名。但Mybatis-plus默认配置了下划线转驼峰命名所以下面的ceateDateupdateDate对应的@TableField可以不用写value属性。
    @TableField注解的fill属性表示字段的填充策略,一共有四种填充策略:
  1. DEFAULT 默认不处理
  2. INSERT 插入时填充
  3. UPDATE 更新时填充
  4. INSERT_UPDATE 插入更新时都填充

在上面的实体类中,我们将createDate设为插入时填充,将updateDate设为插入更新时都填充.

关于更多注解的信息,请查阅官方文档之注解

编写RecordMapper

com.example.mapper包中创建一个RecordMapper接口,并使其继承mybatos-plus提供的BaseMapper<T>接口.

package com.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.pojo.Record;

public interface RecordMapper extends BaseMapper<Record> {
}
实现自己的MetaObjectHandler

虽然我们设置了需要填充的字段的填充策略,但是mybatis-plus并不知道需要填充哪些值,我们还需要创建一个MyMetaObjectHandler类,让它实现MetaObjectHandler接口.并实现其中的insertFillupdateFill方法.

在实现这两个方法时,我们可以调用父类的strictInsertFillstrictUpdateFill方法来进行填充,也可以使用fillStrategy方法来进行填充.

strictInsertFillstrictInsertFill方法签名如下:

default <T, E extends T> MetaObjectHandler strictInsertFill(MetaObject metaObject, String fieldName, Class<T> fieldType, E fieldVal);

这两个方法会根据对应字段的@TableFieldfill设置的填充策略,字段名,字段类型来决定是否进行填充.

例如:若调用了strictUpdateFill方法来填充createDate字段,但是createDate字段上的注解标明的填充策略却是TableFill.INSERT时,将不会进行填充.当字段名对应的字段的类型不是fieldType时,也不会进行填充.

fillStrategy方法的实现如下:

default MetaObjectHandler fillStrategy(MetaObject metaObject, String fieldName, Object fieldVal) {
        if (getFieldValByName(fieldName, metaObject) == null) {
            setFieldValByName(fieldName, fieldVal, metaObject);
        }
        return this;
    }

此方法不会严格判断填充策略和字段类型,只要对应字段的值为null,就会进行填充.当类型不匹配时会导致异常.

package com.example.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class MyMateObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        // strictInsertFill 和 strictUpdateFill 会根据注解中的TableFill策略,字段名和字段类型来判断是否进行填充
        this.strictInsertFill(metaObject,"createDate",LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject,"updateDate",LocalDateTime.class, LocalDateTime.now());
        // strictStrategy方法 只要填充策略不为DEFAULT,且字段名能对上就会填充
        //this.fillStrategy(metaObject,"createDate",LocalDateTime.now());
        //this.fillStrategy(metaObject,"updateDate",LocalDateTime.now());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject,"updateDate",LocalDateTime.class, LocalDateTime.now());
    }
}
编写测试类
package com.example;

import com.example.mapper.RecordMapper;
import com.example.pojo.Record;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@SpringBootTest
@RunWith(SpringRunner.class)
public class AutoFillTests {
    @Resource
    RecordMapper mapper;

    @Test
    public void testInsert(){
        Record record = new Record();
        record.setName("record_one");
        mapper.insert(record);
    }

    @Test
    public void testUpdate(){
        UpdateWrapper<Record> wrapper = new UpdateWrapper<>();
        wrapper.eq("id",1);
        Record record = new Record();
        record.setName("record1");
        mapper.update(record,wrapper);
    }
}

先测试插入,生成sql代码如下:

==>  Preparing: INSERT INTO record ( record_name, create_date, update_date ) VALUES ( ?, ?, ? )
==> Parameters: record_one(String), 2021-10-25T11:16:30.834(LocalDateTime), 2021-10-25T11:16:30.837(LocalDateTime)
<==    Updates: 1

可见,插入时mybatis-plus根据规则对create_date,update_date两个字段进行了填充.

再测试更新,生成sql代码如下:

==>  Preparing: UPDATE record SET record_name=?, update_date=? WHERE (id = ?)
==> Parameters: record1(String), 2021-10-25T12:12:59.954(LocalDateTime), 1(Integer)
<==    Updates: 1

可见,在更新时,mybatis-plus自动填充了update_date字段.