MyBatis-Plus踩坑笔记

出于补充mb-plus 2.x版本文档编写不够详尽部分的目的编写本篇内容,作者水平有限,仅对类似问题提供思路。叠甲,过!


本篇介绍mb-plus提供的两个扩展功能的实践:公共字段自动填充和通用枚举自动注入,分别提供数据表公共字段(创建时间、创建人等)在行记录新增/更新时的自动填充功能,行记录中数据字典代码序列化(to json)时找到对应数据字典名称能力。使用扩展功能时应阅读2.x版本文档,结合阅读博客文章和3.x文档,以尽量避免踩坑。


  • jdk:jdk1.8.0

  • springboot:2.1.3

  • mybatis-plus:2.3.3


一、通用枚举扫描并自动关联注入

1. 创建枚举类,必须实现 IEnum 接口


public enum AgeEnum implements IEnum {
    ONE(1, "一岁"),
    TWO(2, "二岁");

    private int value;
    private String desc;

    AgeEnum(final int value, final String desc) {
        this.value = value;
        this.desc = desc;
    }

    @Override
    public Serializable getValue() {
        return this.value;
    }
    
    public String getDesc(){
        return this.desc;
    }
}

2. 在配置文件(e.g.application.yml)中配置扫描枚举的路径

mybatis-plus:
    typeEnumsPackage: top.hanjiale.enums

3. 在实体类(entity)中改写需要带出数据字典名称(字典描述)的属性

@ApiModelProperty(value = "值班类型")
@TableField("duty_type")
private AgeEnum age;

注意,这里的age属性的类型不是Int也不是String,而是我们第一步创建的枚举类AgeEnum

4. 序列化时带出字典名称

这里介绍jackson,Fastjson官方文档较详细,仅列出

jackson

注意,这里需要数据库中存储的数据字典代码与枚举类的枚举类型名相同,在本例中,数据表内保存的文本可以是ONE、TWO,但不可以是数字1、2
若在AgeEnum的getDesc方法上标记@JsonValue:

@JsonValuepublic 
String getDesc(){    return this.desc;}

则前端得到
"age": "一岁"
若在枚举上标记@JsonFormat(shape= JsonFormat.Shape.OBJECT):

@JsonFormat(shape= JsonFormat.Shape.OBJECT)
public enum DutyTypeEnum implements IEnum {
……
}

则前端得到
"age": {"value": "1","desc": "一岁"}

Fastjson

1.全局处理方式

    FastJsonConfig config = new FastJsonConfig();
    //设置WriteEnumUsingToString
    config.setSerializerFeatures(SerializerFeature.WriteEnumUsingToString);
    converter.setFastJsonConfig(config);

2.局部处理方式

    @JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
    private UserStatus status;

以上两种方式任选其一,然后在枚举中复写toString方法即可。

5.反序列化

当前端传入时,若值无法匹配枚举,会报错。

二、公共字段自动填充

1、在实体类中标记需要自动填充的属性

使用 @TableField(.. fill = FieldFill.INSERT):

/** 创建时间 */
@TableField(value = "created_date",fill = FieldFill.INSERT)
private Date createdDate;

这里的FieldFill用于指定在何种情况自动填充,有如下可选值

  • DEFAULT:默认不处理

  • INSERT:插入时自动填充字段

  • UPDATE:更新时自动填充字段

  • INSERT_UPDATE:插入和更新时自动填充字段

2、创建自定义处理器MyMetaObjectHandler

这里提供一个简短的例子,以期跑通流程,填充内容和逻辑可结合其它博文自行编写

public class MyMetaObjectHandler extends MetaObjectHandler {
    public class MyMetaObjectHandler extends MetaObjectHandler {
        /**     * 测试 user 表 createdDate 字段为空自动填充     */
        @Override   
     public void insertFill(MetaObject metaObject) {
     Object created_by = getFieldValByName("createdBy", metaObject);       
        if (createdDate == null) {           
            setFieldValByName("createdDate", new Date(), metaObject);       
        }       
    }
}

在本例的mp-plus版本中,此自定义处理器类就是继承MetaObjectHandler,而非实现IMetaObjectHandler,官方文档应该是需要维护而未维护
注意,这里的"createdDate"为实体类内的属性名,不是字段名

3、在Mybatis-Plus配置中注册自定义处理器

若使用DataSourceConfig.java,则在setSqlSessionFactory方法中加入:

MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
GlobalConfiguration globalConfig = new GlobalConfiguration();
globalConfig.setMetaObjectHandler(new MyMetaObjectHandler());
bean.setGlobalConfig(globalConfig);

若使用mybatis-config.xml,则


<!-- MyBatis SqlSessionFactoryBean 配置 --> 
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
    <property name="globalConfig" ref="globalConfig"></property>
    </bean> 
    <bean id="globalConfig"  class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
    <!-- 公共字段填充处理器 --> 
    <property name="metaObjectHandler" ref="myMetaObjectHandler" /> 
    </bean>
    <!-- 自定义处理器 -->
    <bean id="myMetaObjectHandler" class="com.baomidou.test.MyMetaObjectHandler" />

Q.E.D.