| @Author:TTODS
前言
MyBatisPlus提供了非常好用的字段填充功能,可以在插入记录或更新记录的时候,根据设定的规则为字段填充指定的值。本文将演示如何使用MybatisPlus的字段填充功能,自动填充表中记录的更新时间字段及插入时间字段。
新建一个测试表record
在数据库中新建一个record
表,该表一共有四个字段:
- id 编号
- record_name 记录名
- create_date 插入日期
- 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`)
);
创建好的表结构如下:
编写实体类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
默认配置了下划线转驼峰命名所以下面的ceateDate
与updateDate
对应的@TableField
可以不用写value
属性。@TableField
注解的fill属性表示字段的填充策略,一共有四种填充策略:
-
DEFAULT
默认不处理 -
INSERT
插入时填充 -
UPDATE
更新时填充 -
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
接口.并实现其中的insertFill
和updateFill
方法.
在实现这两个方法时,我们可以调用父类的strictInsertFill
与strictUpdateFill
方法来进行填充,也可以使用fillStrategy
方法来进行填充.
strictInsertFill
和strictInsertFill
方法签名如下:
default <T, E extends T> MetaObjectHandler strictInsertFill(MetaObject metaObject, String fieldName, Class<T> fieldType, E fieldVal);
这两个方法会根据对应字段的@TableField
的fill
设置的填充策略,字段名,字段类型来决定是否进行填充.
例如:若调用了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
字段.