mybatis-plus 公共字段填充(自定义)

发布时间 2023-06-02 15:26:57作者: shirleyLee

mybatisplus带的公共字段自动填充

通常,记录数据时会存在公共字段,为了方便插入,可以使用mybatisplus带的公共字段自动填充, 例如:记录创建信息和更新信息

@ApiModelProperty(value = "创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT, updateStrategy = FieldStrategy.IGNORED)
private Date createTime;

@ApiModelProperty(value = "创建人id")
@TableField(value = "create_user_id", fill = FieldFill.INSERT)
private Long createUserId;

@ApiModelProperty(value = "创建人姓名")
@TableField(value = "create_user_name", fill = FieldFill.INSERT)
private String createUserName;

@ApiModelProperty(value = "修改时间")
@TableField(value = "update_time", fill = FieldFill.UPDATE)
private Date updateTime;

@ApiModelProperty(value = "修改人id")
@TableField(value = "update_user_id", fill = FieldFill.UPDATE)
private Long updateUserId;

@ApiModelProperty(value = "修改人姓名")
@TableField(value = "update_user_name", fill = FieldFill.UPDATE)
private String updateUserName;

 

存在这么一种情况,当我没有赋值这个数据的时候自动插入,如果赋值了就插入自己的值。

自动填充步骤:

1、在实体类的属性上加入@TableField注解,指定自动填充策略

2、按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,需要实现MetaObjectHandler接口

3、 使用:

  fill = FieldFill.INSERT             新增
  fill = FieldFill.INSERT_UPDATE 新增和修改
  fill = FieldFill.UPDATE      修改

 

CustomMetaObjectHandler.java

@Component
public class CustomMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        //【注意】属性名称,不是字段名称
        if (Objects.isNull(curUserId) && metaObject.hasGetter("createUserId") && Objects.isNull(metaObject.getValue("createUserId"))) {
            this.setFieldValByName("createUserId", 1L, metaObject);
        }
        Object createUserId = this.getFieldValByName("createUserId", metaObject);
        //对于手动赋值的数据,不再自动赋值
        if(Objects.nonNull(createUserId))
        {
            //System.out.println(createUserId);
        }
        else if (Objects.nonNull(curUserId)) {
            this.setFieldValByName("createUserId", curUserId, metaObject);
        }

        Object createUserName = this.getFieldValByName("createUserName", metaObject);
        if(createUserName instanceof String && StringUtils.isNotBlank((String)createUserName))
        {
            //System.out.println(createUserName);
        }
        else
        {
            this.setFieldValByName("createUserName", CommonUtil.getCurrentUserName(), metaObject);
        }

        Object createTime = this.getFieldValByName("createTime", metaObject);
        if(createTime != null)
        {
//            System.out.println(createTime);
        }
        else
        {
            this.setFieldValByName("createTime", CommonUtil.getCurrentDate(), metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        //如果有需要,同上
        this.setFieldValByName("updateTime", CommonUtil.getCurrentDate(), metaObject);
        this.setFieldValByName("updateUserId", CommonUtil.getCurrentUserId(), metaObject);
        this.setFieldValByName("updateUserName", CommonUtil.getCurrentUserName(), metaObject);
    }
}

 

这里,如果存在项目中重写SqlSessionFactory,需要添加配置:

@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(
    @Qualifier("mybatisPlusInterceptor") MybatisPlusInterceptor mybatisPlusInterceptor,
    CustomMetaObjectHandler customMetaObjectHandler
    ) throws Exception {
        MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(buildDataSource());
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/**/*.xml"));
        sessionFactoryBean.setPlugins(mybatisPlusInterceptor);
        GlobalConfig globalConfig = new GlobalConfig();
        //这里!!
        globalConfig.setMetaObjectHandler(customMetaObjectHandler);
        globalConfig.setSqlInjector(new MyInjector());
        sessionFactoryBean.setGlobalConfig(globalConfig);
        return sessionFactoryBean.getObject();
    }

 

 【补充】

MybatisPlus 字段更新策略 FieldStrategy使用

Mybatis-plus默认的更新策略是NOT_NULL:非NULL,也就是传数据为NULL时不更新数据库中该字段的值。

Mybatis-plus通过updateById()更新数据,当传值为NULL且需要对该字段更新为NULL时,需要对FieldStrategy 策略进行调整。

public enum FieldStrategy {
    //忽略空值判断,实体对象的字段是什么值就用什么值更新,支持null值更新操作
    IGNORED,
    //非NULL判断
    NOT_NULL,
    //非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断)
    NOT_EMPTY,
    //默认
    DEFAULT,
    //不加入 SQL
    NEVER
}

 

第一种:在配置文件中全局配置

//默认都是DEFAULT,也就是NOT_NULL
mybatis-plus.global-config.db-config.update-strategy=not_null
mybatis-plus.global-config.db-config.insert-strategy=not_null
mybatis-plus.global-config.db-config.where-strategy=not_null

 

第二种:单个字段

@ApiModelProperty(value = "创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT, updateStrategy = FieldStrategy.IGNORED)
private Date createTime;

 

实战:

@Data
@TableName("rewrite_sql")
public class RewriteSqlDO implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.INPUT)
    private Integer id;

    private String stuName;

    private Integer age;

    @TableField(value = "create_time", fill = FieldFill.INSERT,  updateStrategy = FieldStrategy.IGNORED)
//    @TableField(value = "create_time", fill = FieldFill.INSERT,  updateStrategy = FieldStrategy.NOT_NULL)
//    @TableField(value = "create_time", fill = FieldFill.INSERT,  updateStrategy = FieldStrategy.NOT_EMPTY)
//    @TableField(value = "create_time", fill = FieldFill.INSERT,  updateStrategy = FieldStrategy.NEVER)
    private Date createTime;
}

初始值:

@Test
void test4() {
    //测试策略
    RewriteSqlDO rewriteSqlDO = new RewriteSqlDO();
    rewriteSqlDO.setId(1);
    rewriteSqlDO.setAge(2);
    rewriteSqlDO.setStuName(String.valueOf(2));
    //        rewriteSqlDO.setCreateTime(TimeUtil.sdfStrToDate("2023-12-31", "yyyy-MM-dd"));
    rewriteSqlMapper.updateById(rewriteSqlDO);
}

 

1、FieldStrategy.IGNORED

结果:忽略字段值的空值判断,无论实体对象的字段值是否为空,都会进行更新操作。

【注意:】如果传的值为空,则更新为NULL。

 

2、FieldStrategy.NOT_NULL

结果:进行NULL值判断,如果为NULL,则不更新对应的字段。

 

3、FieldStrategy.NOT_EMPTY

结果:字符串进行空值判断,只有非空字符串的字段才会参处理与数据。

 

3、FieldStrategy.NOT_EMPTY

结果:字符串进行空值判断,只有非空字符串的字段才会参处理与数据。

 

4、FieldStrategy.NEVER

结果:忽略字段值的空值判断,不管标识的字段是否有值,都不会进行更新操作。

@Test
void test4() {
    RewriteSqlDO rewriteSqlDO = new RewriteSqlDO();
    rewriteSqlDO.setId(1);
    rewriteSqlDO.setAge(2);
    rewriteSqlDO.setStuName(String.valueOf(2));
    rewriteSqlDO.setCreateTime(TimeUtil.sdfStrToDate("2023-12-31", "yyyy-MM-dd"));
    rewriteSqlMapper.updateById(rewriteSqlDO);
}

 

 

 这里引出了一个问题: update_time字段未自动更新

当使用selectById()时,没有进行自动更新create_time。原因就是:默认的是NOT_NULL,当赋值的时候没有重新赋值这个值,那么就不会更新。

需要注意。解决方案如上,更换其他策略。