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

 更新时间:2022年05月17日 16:30:36   作者:五更依旧朝花落  
本文主要介绍了Mybatis-plus自动填充不生效或自动填充数据为null原因及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

昨天使用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自动填充内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java设计模式七大原则之合成复用原则详解

    Java设计模式七大原则之合成复用原则详解

    合成复用原则(Composite Reuse Principle),即尽量使用组合/聚合的方式,而不是使用继承。本文将为大家具体介绍一下Java设计模式七大原则之一的合成复用原则,需要的可以参考一下
    2022-02-02
  • Struts2开发 基本配置与类型转换

    Struts2开发 基本配置与类型转换

    本篇文章,小编将为大家介绍关于Struts2开发 基本配置与类型转换,有需要的朋友可以参考一下
    2013-04-04
  • JAVA面试题 start()和run()详解

    JAVA面试题 start()和run()详解

    这篇文章主要介绍了JAVA面试题 启动线程是start()还是run()?为什么?,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • 详解如何实现OpenAPI开发动态处理接口的返回数据

    详解如何实现OpenAPI开发动态处理接口的返回数据

    这篇文章主要为大家介绍了OpenAPI开发动态处理接口的返回数据如何实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Java使用CompletableFuture进行非阻塞IO详解

    Java使用CompletableFuture进行非阻塞IO详解

    这篇文章主要介绍了Java使用CompletableFuture进行非阻塞IO详解,CompletableFuture是Java中的一个类,用于支持异步编程和处理异步任务的结果,它提供了一种方便的方式来处理异步操作,并允许我们以非阻塞的方式执行任务,需要的朋友可以参考下
    2023-09-09
  • 使用Spring AOP实现用户操作日志功能

    使用Spring AOP实现用户操作日志功能

    这篇文章主要介绍了使用Spring AOP实现了用户操作日志功能,功能实现需要一张记录日志的log表,结合示例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • Java咖啡馆(1)——叹咖啡

    Java咖啡馆(1)——叹咖啡

    这篇文章主要给大家介绍了关于Java咖啡馆之叹咖啡,需要的朋友可以参考下
    2006-12-12
  • java使用minio上传下载文件完整版教程

    java使用minio上传下载文件完整版教程

    本示例教程介绍了如何使用SpringBoot框架结合MinIO服务实现文件的上传和下载功能,并将文件信息存储在数据库的file表中,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-09-09
  • 浅谈一下Java中的访问修饰符以及作用

    浅谈一下Java中的访问修饰符以及作用

    这篇文章主要介绍了浅谈一下Java中的访问修饰符以及作用,修饰符修饰的是“被访问”的权限,所有修饰符都可以修饰成员变量,方法,构造方法,需要的朋友可以参考下
    2023-05-05
  • IDEA 服务器热部署图文详解(On Update action/On frame deactivation)

    IDEA 服务器热部署图文详解(On Update action/On frame deactivation)

    这篇文章主要介绍了IDEA 服务器热部署详解(On Update action/On frame deactivation),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03

最新评论