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

作者:五更依旧朝花落 时间:2021-08-16 02:18:42 

昨天使用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就会出现这种情况

来源:https://blog.csdn.net/m0_37628958/article/details/106633132

标签:Mybatis-plus,自动填充
0
投稿

猜你喜欢

  • Android中AlertDialog四种对话框的最科学编写用法(实例代码)

    2021-09-07 10:25:58
  • 教你怎么用Java操作Redis

    2023-07-07 22:17:53
  • WCF实现进程间管道通信Demo分享

    2022-10-22 04:20:06
  • 简单掌握Android开发中彩信的发送接收及其附件的处理

    2023-04-18 02:32:24
  • android用java动态增添删除修改布局

    2021-07-04 12:48:38
  • 代码分析Android实现侧滑菜单

    2022-04-02 16:38:45
  • Android基于OpenCV实现Harris角点检测

    2023-07-16 12:19:47
  • Android APP存活检测方式

    2023-10-14 10:02:41
  • java 中Map详解及实例代码

    2023-06-06 01:27:37
  • Java实现FTP上传到服务器

    2022-10-07 10:28:58
  • Android studio实现PopupWindow弹出框效果

    2021-12-19 11:12:50
  • Flutter Android应用启动白屏的解决方案

    2022-10-02 04:08:04
  • Android实现手机震动抖动效果的方法

    2023-01-25 07:27:43
  • java基于JDBC连接Oracle 11g Release2实例分析

    2022-06-06 02:36:36
  • Java内存溢出案例模拟和原理分析过程

    2023-04-09 07:27:48
  • 详解Android中Handler的内部实现原理

    2023-05-11 12:50:12
  • C#中Linq的入门教程

    2023-12-23 16:20:52
  • springboot jpa 延迟加载问题的2种解决

    2021-10-14 03:05:20
  • Spring4整合Hibernate5详细步骤

    2022-03-15 16:53:07
  • kotlin 定义接口并实现回调的例子

    2022-12-06 14:30:19
  • asp之家 软件编程 m.aspxhome.com