【Java教程】Mybatis-plus自动填充数据不生效或null原因及解决方法

零 Java教程评论82字数 3791阅读12分38秒阅读模式

所需工具:

Java

聪明的大脑文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

勤劳的双手文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

 文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

注意:本站只提供教程,不提供任何成品+工具+软件链接,仅限用于学习和研究,禁止商业用途,未经允许禁止转载/分享等文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

 文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

介绍

自动填充的数据为null
使用mybatis-plus的乐观锁后发现自动填充的updateTime字段不自动填充了文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

 文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

教程如下

我使用的版本是3.3.2文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

如果想省时间,前面的问题描述和分析过程不用看,直接根据目录跳到小结就好了。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

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

原因:[填充的数据类型] 和 [实体类定义的数据类型] 不一致。例如你的updateTime是 java.util.Date类型的。但是填充的是LocalDateTime(因为官网给个就是这个,可能就是直接用了)。这就会导致填充的数据为空。文章源自灵鲨社区-https://www.0s52.com/bcjc/javajc/12040.html

参考如下定义

[php]

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

[/php]

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

[php]

@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 有多个方法,详细查看源码) */
}
}

[/php]

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

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

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

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

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

示例:

[php]

@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);
}

[/php]

原因:

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

[php]

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

return this;
}

[/php]

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

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

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

[php]

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

return this;
}

[/php]

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

[php]

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

}

[/php]

小结

填充的方法一共有三个

[php]

// 这个是通用的,插入和更新都可以使用 但是当字段存在值 的时候不进行填充
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(推荐使用)

[/php]

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

零
  • 转载请务必保留本文链接:https://www.0s52.com/bcjc/javajc/12040.html
    本社区资源仅供用于学习和交流,请勿用于商业用途
    未经允许不得进行转载/复制/分享

发表评论