MybatisPlus - updateFill (strictUpdateFill)更新时间 自动填充失败

建议直接看原文MybatisPlus - updateFill (strictUpdateFill)更新时间 自动填充失败

之前写的文章@TableField(fill = FieldFill.INSERT)并没有细写MetaObjectHandler,这里补充一下(因为遇到bug了)

MP官方给出的自动填充插入和更新时间的方法
https://baomidou.com/pages/4c6bcf/

项目实际举例

第一:后端接收实体类,在继承的BaseEntity添加@TableField

package com.njry.sjzl.busi.domain;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.njry.base.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotNull;
import java.io.Serializable;

@Data
@TableName("T_ATOM_TEMPLATE")
public class AtomTemplate extends BaseEntity implements Serializable {

    @NotNull(groups = Update.class)
    @TableId(value="template_id", type = IdType.INPUT)
    @ApiModelProperty(value = "ID", hidden = true)
    private Long id;

    @ApiModelProperty(value = "模板id   seq_t_atom_Template")
    private String templateId;

    @ApiModelProperty(value = "模板名称")
    private String templateName;

    @ApiModelProperty(value = "模板备注")
    private String templateDesc;

    @ApiModelProperty(value = "状态 1 有效  0 无效")
    private Integer status;

    @ApiModelProperty(value = "maxLevel")
    private Integer maxLevel;

    @ApiModelProperty(value = "排序")
    private Long showOrder;

    @ApiModelProperty(value = "路径")
    private String path;

    @ApiModelProperty(value = "组织表名称")
    private String orgTable;

    public void copy(AtomTemplate source){
        BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
    }
}

package com.njry.base;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.LastModifiedBy;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.Timestamp;

/**
 * 通用字段, is_del 根据需求自行添加
 * @author 
 * @Date 2024年05月11日
 */
@Getter
@Setter
public class BaseEntity implements Serializable {

    @CreatedBy
    @TableField(fill = FieldFill.INSERT)
    @ApiModelProperty(value = "创建人", hidden = true)
    private String createBy;

    @LastModifiedBy
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty(value = "更新人", hidden = true)
    private String updateBy;

    @TableField(fill = FieldFill.INSERT)
    @ApiModelProperty(value = "创建时间", hidden = true)
    private Timestamp createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty(value = "更新时间", hidden = true)
    private Timestamp updateTime;

    /* 分组校验 */
    public @interface Create {}

    /* 分组校验 */
    public @interface Update {}

    @Override
    public String toString() {
        ToStringBuilder builder = new ToStringBuilder(this);
        Field[] fields = this.getClass().getDeclaredFields();
        try {
            for (Field f : fields) {
                f.setAccessible(true);
                builder.append(f.getName(), f.get(this)).append("\n");
            }
        } catch (Exception e) {
            builder.append("toString builder encounter an error");
        }
        return builder.toString();
    }
}

在这里插入图片描述

第二:自定义类继承MetaObjectHandler

package com.njry.config.mybatis;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.njry.utils.SecurityUtils;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.sql.Timestamp;

/**
 * @author wj
 * @date 2024-05-11
 **/
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        /* 创建时间 */
        this.strictInsertFill(metaObject, "createTime", Timestamp.class, DateTime.now().toTimestamp());
        this.strictInsertFill(metaObject, "updateTime", Timestamp.class, DateTime.now().toTimestamp());

        /* 任务管理加创建时间改个字段名称 */
        this.strictInsertFill(metaObject, "createDate", Timestamp.class, DateTime.now().toTimestamp());
        this.strictInsertFill(metaObject, "modifyDate", Timestamp.class, DateTime.now().toTimestamp());
        /* 操作人 */
        String username = "System";
        try {username = SecurityUtils.getCurrentUsername();}catch (Exception ignored){}
        this.strictInsertFill(metaObject, "createBy", String.class, username);
        this.strictInsertFill(metaObject, "updateBy", String.class, username);

        /* 任务管理加操作人改个字段名称 */
        this.strictInsertFill(metaObject, "createOperator", String.class, username);
        this.strictInsertFill(metaObject, "modifyOperator", String.class, username);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        /* 更新时间 */
        this.strictUpdateFill(metaObject, "updateTime", Timestamp.class, DateTime.now().toTimestamp());
//        this.setFieldValByName("updateTime", DateTime.now().toTimestamp(), metaObject);
        /* 任务管理加更新时间改个字段名称 */
        this.strictUpdateFill(metaObject, "modifyDate", Timestamp.class, DateTime.now().toTimestamp());
//        this.setFieldValByName("modifyDate", DateTime.now().toTimestamp(), metaObject);
        /* 操作人 */
        String username = "System";
        try {username = SecurityUtils.getCurrentUsername();}catch (Exception ignored){}
        this.strictUpdateFill(metaObject, "updateBy", String.class, username);
//        this.setFieldValByName("updateBy", username, metaObject);
        /* 任务管理加操作人改个字段名称 */
        this.strictUpdateFill(metaObject, "modifyOperator", String.class, username);
//        this.setFieldValByName("modifyOperator", username, metaObject);
    }
}


问题来了
插入数据时,插入时间和更新时间都发生了变化。
但是,在使用更新数据时,使用 this.strictUpdateFill(metaObject, “updateTime”, Timestamp.class, DateTime.now().toTimestamp()),数据库updata_time字段无法更新成功。

原因
官方文档给出注意事项:
MetaObjectHandler提供的默认方法的策略均为: 如果属性有值则不覆盖, 如果填充值为null则不填充。也就是说,MP的自动填充功能的前提是填充字段要求为null。

这确实是个大坑,而且是官方给的大坑,很烦。

解决办法

1、换方法,使用 this.setFieldValByName(“updateTime”, LocalDateTime.now(), metaObject);(最简单,使用老方法)

2、修改前设置数据库字段为null(麻烦)

3、自己重写源代码方法(有一定经验的小伙伴可以尝试,下面是断点找到在哪里修改)

debug更新
在这里插入图片描述
前段修改模版备注请求编辑
在这里插入图片描述
进入断点
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这一步是过滤更新字段在不在当前实体类中,这就是可以在updateFill里面多次调用strictUpdateFill不用担心有的表数据有这个字段有的没有
在这里插入图片描述
我的是mybatis-plus3.5.3.1源码 MetaObjectHandler的处理(如下)
在这里插入图片描述
断点继续就执行下一个this.strictUpdateFill
我下一个更新字段是modifyDate,直接在第一步过滤就结束了,期许在罪魁祸首哪一步也结束了
结果就是bug
在这里插入图片描述
省事就用老方法setFieldValByName,修改源码改麻烦
interface MetaObjectHandler 的 setFieldValByName方法

   default MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) {
        if (Objects.nonNull(fieldVal) && metaObject.hasSetter(fieldName)) {
            metaObject.setValue(fieldName, fieldVal);
        }

        return this;
    }

相关推荐

  1. Mybtisplus时间字段进行自动填充

    2024-06-07 00:28:03       64 阅读
  2. mybatisplus实现自动创建/更新时间

    2024-06-07 00:28:03       62 阅读
  3. MybatisPlus自动生成代码

    2024-06-07 00:28:03       42 阅读
  4. mybatis-Plus 的自动填充

    2024-06-07 00:28:03       50 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-07 00:28:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-07 00:28:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-06-07 00:28:03       87 阅读
  4. Python语言-面向对象

    2024-06-07 00:28:03       96 阅读

热门阅读

  1. Emacs Verilog Mode 简单使用指南

    2024-06-07 00:28:03       35 阅读
  2. 【Qt快速入门(一)】- Qt简介

    2024-06-07 00:28:03       27 阅读
  3. js平滑滚动元素使其可见

    2024-06-07 00:28:03       33 阅读
  4. C++在构造函数中使用new

    2024-06-07 00:28:03       31 阅读
  5. zs6d配置-2

    2024-06-07 00:28:03       27 阅读
  6. 7-14 字节序(Endianness)---PTA实验C++

    2024-06-07 00:28:03       30 阅读
  7. 自然语言处理中的BERT模型深度剖析

    2024-06-07 00:28:03       32 阅读
  8. C++day3

    C++day3

    2024-06-07 00:28:03      30 阅读
  9. 用增之Google GA4F

    2024-06-07 00:28:03       31 阅读
  10. 前端经验:导出表格为excel并设置样式

    2024-06-07 00:28:03       33 阅读
  11. 维纳运动的概念

    2024-06-07 00:28:03       35 阅读
  12. 后端开发面经系列 -- 同程旅行C++一面

    2024-06-07 00:28:03       27 阅读
  13. 力扣 383题 赎金信 记录

    2024-06-07 00:28:03       32 阅读