Mybatis-plus自动填充不生效或自动填充数据为null原因及解决方案

目录
  • 问题一:自动填充的数据为null
  • 问题二:使用mybatis-plus的乐观锁后发现自动填充的updateTime字段不自动填充了
  • 小结

昨天使用mybatis-plus。使用自动填充后发现了两个问题。

  • 一个是填充数据为null,
  • 一个是当使用了mybatis-plus的乐观锁,自动填充就失效了

开始在网上看,有人说是mybatis的bug,我想不会我这么快就遇到了bug。后面我通过idea的(ctrl+B)看他的源码.发现这不是bug,而是一个非常巧妙的设计,当然也可能是之前有bug,我用的版本是正常的

mybatis官网自动填充功能说明
我使用的版本是3.3.2

如果想省时间,前面的问题描述和分析过程不用看,直接根据目录跳到小结就好了。

问题一:自动填充的数据为null

原因:[填充的数据类型] 和 [实体类定义的数据类型] 不一致。例如你的updateTime是 java.util.Date类型的。但是填充的是LocalDateTime(因为官网给个就是这个,可能就是直接用了)。这就会导致填充的数据为空。

参考如下定义

this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());

以下是官网给的示范:(我把那两个过期方法去掉了)

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
        this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)
        /* 上面选其一使用,下面的已过时(注意 strictInsertFill 有多个方法,详细查看源码) */
       
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
        this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)
        /* 上面选其一使用,下面的已过时(注意 strictUpdateFill 有多个方法,详细查看源码) */
    }
}

问题二:使用mybatis-plus的乐观锁后发现自动填充的updateTime字段不自动填充了

该问题还有其他描述:从数据库查出来的数据,无法进行自动填充

本质原因:当该字段有值之后,自动填充不进行填充,里面的数据还是原值

下面两段代码,testUpdateUser和testOptimisticLocker。前者updateTime进行了自动填充,后者没有进行自动填充。

原因是后者的User对象所有字段的值都从数据库查出来,并进行了赋值。然后自动填充数据没有填充数据

示例:

    @Test
    public void testUpdateUser(){
        User user = new User();
        user.setId(7L);
        user.setName("喻文波");
        int rows = userMapper.updateById(user);
        System.out.println(rows);
    }
    /**
     * 测试乐观锁
     */
    @Test
    public void testOptimisticLocker(){
        // 先查询一个用户
        User user = userMapper.selectById(8L);
        System.out.println(user);
        // 修改用户观察version是否更新
        user.setName("pdd");
        user.setEmail("PDD@163.com");
        int rows = userMapper.updateById(user);
        System.out.println(rows);
    }

原因:

填充用的方法是:this.fillStrategy(metaObject,"updateTime",new Date());,这是官网提供的方法之一
我们ctrl+B进去看下

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

        return this;
    }

发现就是故意这样设计的,当你要填充的字段 fieldName对应的字段为空时才进行自动填充,否则不进行填充
然后我又看了官网提供的另一个方法this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
ctrl+B 看下源码

最终调用的是下面这个。有点长。一看就不想看

然后我strict的意思,严格的。我推测这个应该就是说强制执行的意思,不管是否有原值都强制执行更新。然后我试了下,果然就是这样的

    default MetaObjectHandler strictFill(boolean insertFill, TableInfo tableInfo, MetaObject metaObject, List<StrictFill> strictFills) {
        if (insertFill && tableInfo.isWithInsertFill() || !insertFill && tableInfo.isWithUpdateFill()) {
            strictFills.forEach((i) -> {
                String fieldName = i.getFieldName();
                tableInfo.getFieldList().stream().filter((j) -> {
                    return j.getProperty().equals(fieldName) && i.getFieldType().equals(j.getPropertyType()) && (insertFill && j.isWithInsertFill() || !insertFill && j.isWithUpdateFill());
                }).findFirst().ifPresent((j) -> {
                    this.strictFillStrategy(metaObject, fieldName, i.getFieldVal());
                });
            });
        }

        return this;
    }

最后总结:
insert也是一样的。

   @Override
    public void updateFill(MetaObject metaObject) {
        // 如果有值,则不会更新
       // this.fillStrategy(metaObject,"updateTime",new Date());
        // 即使有值,也更新为当前时间
       this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());

    }

小结

填充的方法一共有三个

// 这个是通用的,插入和更新都可以使用 但是当字段存在值 的时候不进行填充
this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)
// 这个是insert的时候用的,插入的时候时候强制进行填充
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
// update的时候使用,更新的时候强制进行填充
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)

注意填充的类型,要和你定义字段的类型一致,不然就可能出现填充为为空值的情况 例如原值是java.util.Date ,填充的LocalDateTime就会出现这种情况

到此这篇关于Mybatis-plus自动填充不生效或自动填充数据为null原因及解决方案的文章就介绍到这了,更多相关Mybatis-plus自动填充内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mybatis-Plus自动填充的实现示例

    在常用业务中有些属性需要配置一些默认值,MyBatis-Plus提供了实现此功能的插件.在这里修改user表添加 create_time 字段和 update_time 字段,在User类中添加对应属性. 1.为需要自动填充的属性添加注解 @TableField 提供了4种自动填充策略:DEFAULT,默认不处理.INSERT,插入填充字段.UPDATE,更新填充字段.INSERT_UPDATE,插入和更新填充字段. @Data public class User { private Long

  • MyBatis-Plus自动填充功能失效导致的原因及解决

    1:先检查 字段有没有加上注解 @TableField(fill = FieldFill.INSERT_UPDATE) @TableField(fill = FieldFill.INSERT_UPDATE) private Date updatedTime; 2:有没有实现 MetaObjectHandler 接口 ,并且加入到 Spring 容器中 @Component public class MyMetaObjectHandler implements MetaObjectHandler

  • MyBatis-Plus实现字段自动填充功能的示例

    目录 一.前言 二.实现 1. 实体类 2. 公用字段 - 使用注解填充字段 3. 自定义MyMetaObjectHandler字段自动填充处理类继承MetaObjectHandler 一.前言 在项目中,我们有一些公共的字段需要做修改 如: gmt_create:创建时间 creator_id:创建人 gmt_modified:修改时间 modifier_id:修改人 这时候我们可以采用 MyBatis-Plus 中的字段自动填充功能去实现 思路:抽取公用字段封装到BaseEntity类中,再

  • MyBatis-Plus 修改和添加自动填充时间方式

    MyBatis-Plus 修改和添加自动填充时间 数据库字段设置: `valid_verify_time` datetime DEFAULT NULL COMMENT '有效性审核时间', 实体类设置: @JsonSerialize:序列化 @JsonDeserialize:反序列化 LocalDateTimeSerializer:JDK时间序列化规则 @ApiModelProperty(value = "有效性审核时间") @TableField(fill = FieldFill.U

  • mybatis-plus自动填充插入更新时间有8小时时差

    今天使用mybatis-plus自动填充插入和更新时间有8小时时差 后来发现只需要修改一下mybaits连接的url即可 原先我是用的 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/gulischool?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username: root passw

  • Mybatis-plus自动填充不生效或自动填充数据为null原因及解决方案

    目录 问题一:自动填充的数据为null 问题二:使用mybatis-plus的乐观锁后发现自动填充的updateTime字段不自动填充了 小结 昨天使用mybatis-plus.使用自动填充后发现了两个问题. 一个是填充数据为null, 一个是当使用了mybatis-plus的乐观锁,自动填充就失效了 开始在网上看,有人说是mybatis的bug,我想不会我这么快就遇到了bug.后面我通过idea的(ctrl+B)看他的源码.发现这不是bug,而是一个非常巧妙的设计,当然也可能是之前有bug,我

  • mybatis plus CU自动填充 和 软删除自动填充的实现方法

    说明 CU 是 CRUD 中的创建和修改 本文实现以下需求效果 创建数据时自动填充 createTime 更新数据时自动填充 updateTime(每次修改都自动填充新的 updateTime 值) 软删除数据时自动填充 deleteUserId 和 deleteTime 创建 实体类 为实体类(DO)的 createTime 字段配置以下 Annotation,代表标记在插入(insert into)时自动填充字段值 @TableField(fill = FieldFill.INSERT) p

  • springboot自动配置没有生效的问题定位(条件断点)

    Spring Boot在为开发人员提供更高层次的封装,进而提高开发效率的同时,也为出现问题时如何进行定位带来了一定复杂性与难度.但Spring Boot同时又提供了一些诊断工具来辅助开发与分析,如spring-boot-starter-actuator.本文分享一个基于actuator与IDEA条件断点来定位自动配置未生效的案例.望对类似问题分析与处理提供参考. 问题确认 在前文介绍的 Spring Boot从入门到实战:整合通用Mapper简化单表操作 中,我们对druid连接池做了自动配置,

  • Python之Django自动实现html代码(下拉框,数据选择)

    我就废话不多说了,还是直接看代码吧! #模板 class IndexForm(forms.Form): # 模板,用户提交的name和这里的变量名一定要是一致的.否则不能获取数据 user = forms.CharField(min_length=6, error_messages={'required': '用户名不能为空', 'min_length': '用户名长度不能小于6'}) email = forms.EmailField(error_messages={'required': '邮

  • Thinkphp框架 表单自动验证登录注册 ajax自动验证登录注册

    动态验证:(不需要建Model模型) 1.建一个控制器,做表单操作(包含验证) <?php namespace Biaodan\Controller; use Think\Controller; class BiaodanController extends Controller { public function test() { if(empty($_POST))//如果$_POST空,显示添加页面, { $this->show(); } else //如果$_POST不为空,走验证,验证

  • JS扩展Z-Blog图片验证码的单击自动刷新与评论内容自动保存

    在script/common.js最后加入下面的话可以实现图片验证码的自动刷新与评论内容自动保存(ForIE) 由于Z-Blog的JS扩展机制不够好,在不重建的情况下扩展东西只能用window.onload(IE). 既然用了window.onload,那就干脆用window.clipboardData了. 大家是不是期盼这两个功能很久了?没有了Ajax的,这两个功能就太重要太重要太重要了. 实际这个函数因为先天缺陷并不完美,下一版,构想在每一页下面加上一句话读一次LoadExtraScript

  • 详解JavaEE使用过滤器实现登录(用户自动登录 安全登录 取消自动登录黑用户禁止登录)

    在我们生活中,对于账户的自动登录已经很常见了,所以利用过滤器实现这个功能. 主要介绍用户的自动登录和取消自动登录,以及实现一天自动登录或者n天实现自动登录,当用户ip被加入到黑名单之后,直接利用过滤器返回一个警告页面. 过滤器的功能很是强大,我们只需要在写好的前台后servlet之后进行添加就可以实现这个功能 Ps:这个仅仅只是一个演示而已,里面的访问数据库的部分,自己随意模拟了下,主要是突出实现自动登录的功能. 前台代码: 前台代码是成功与否都在这个页面显示.用到的技术:jstl标签的应用,s

  • Vue.js实现双向数据绑定方法(表单自动赋值、表单自动取值)

    1.使用Vue.js实现双向表单数据绑定,例子 <!--html代码--> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>财产查勘处理</title> <link r

  • shell脚本自动检测网络掉线和自动重连

    在ppp移植成功后,有时会出现ppp掉线等情况.这篇文章写了一个自动检测连接网络的解决方法. 创建一个shell脚本,在里面添加一下内容.(记得给操作权限) #!/bin/sh //根据你自己的shell类型来选择. while true //先做一个死循环 do ping -c 3 -I ppp0 172.16.1.11 >/dev/null //指定一个出口去ping服务器的局域网ip,将结果重定向到/dev/null里. //-c 3 是指ping执行3次后结束. //-w 3 是指pin

  • python爬虫利用selenium实现自动翻页爬取某鱼数据的思路详解

    基本思路: 首先用开发者工具找到需要提取数据的标签列 利用xpath定位需要提取数据的列表 然后再逐个提取相应的数据: 保存数据到csv: 利用开发者工具找到下一页按钮所在标签: 利用xpath提取此标签对象并返回: 调用点击事件,并循环上述过程: 最终效果图: 代码: from selenium import webdriver import time import re class Douyu(object): def __init__(self): # 开始时的url self.start

随机推荐