关于Mybatisplus的@TableFiled注解的自动注入功能产生的槽点

2023年 7月 26日 68.7k 0

最近用Mybatis-plus比较多,这个框架带来的快速开发的效果也比较好,但是,由于技术架构的时间较长,开发团队的不断更新,导致程序设计及开发出现了问题,

注释:该部分代码分析版本来自于Mybatis-plus 3.4.0 版本不同可能有细微差异,仅供参考

(虽然我不觉得这部分基础代码会在版本迭代下进行较大的改动)

问题1:

create_time 字段从 因为项目组开发人员不断更新 历史实体类中createTime 默认的 Date类型 在新增的实体类中手中变成了 LocalDateTime 这本身没有什么问题,但是。。。

导致:

新实体类中 在 createTime 字段上 添加 @TableFiled(fill = INSERT) 产生自动注入失败 的问题

原因是:

new Date() 产生的数据是 CST 格式 无法放入 LocalDateTime

结果:

我们的 每个新的实体类 只要采用了 LocalDateTime 的字段设计 就只能用 setCreateTime(LocalDateTime.now()) 的方式来完成时间数据的注入

这就令人很是烦躁!!! 不过,也同样侧面说明了,虽然目前市面上提供的java工具很好用,但要完全兼容历史架构,需要对历史架构足够熟悉,否则,也会影响真实的开发效率

问题2

那createTime没办法偷懒了,我得想办法偷别的字段的懒 !!!要么多对不起程序员,然后就出问题了

这次bug十分意外,在插入createBy的时候,又出现了时间问题???

而且,这次排查的bug还让我学到了一些小东西

排查bug

其实这个bug排查的时间也不久,可以预见性知道一定是注入的问题,但一个决定性问题影响了我的思路

就是在我认知中 Mybatis-plus 应该是只对加了 @TableField(fill = FieldFill.INSERT)的注解进行添加的方法,但让我万万没想到的是,实际上不是这个样子的

翻阅一下Mybatis-plus的插入/更新源码

1690337584049.png

1690337840847.png
其实入参实体就是我们携带了 @TableField(fill = FieldFill.INSERT)所在的 实体类
大概可以理解为:

public class User{

    @TableId(type = IdType.ASSIGN_UUID)
    private String id;
    
    @TableField(fill = FieldFill.INSERT)
    private String name ;
}

这个样子,就是 可以理解为 MateObject 的 数据结构 包含了 这个实体类的,及相关的注解详情

主键生成策略这部分。和我关注这部分关联性不高,直接跳过

1690339721144.png

第一个全局的开启,默认是开启的 可以在实现了 MetaObjectHandler 接口的类下内重写这个方法 直接返回 false 即可关闭

第二个的话,比较神奇,是在启动的时候初始化 entity然后扫描到这个实体类中是否存在了 @TableField(fill = FieldFill.INSERT)注解,只要有一个存在,就为 true

(坑点就在这里)

最终的结果走进了判断, 触发了我心心念念的 metaObjectHandler.insertFill(metaObject)方法

但是metaObject中包含的是整个实体类! createTime也在其中啊!!直接把我的createTime给干掉了,报了个和问题1,一模一样的错误。。

原因

找到原因了,原来是@TableField(fill = FieldFill.INSERT) 在实体类中 只要有一个,就会渲染将整个实体类标注为开启自动填充(虽然没什么问题,但是我最开始是认为精细到字段的,不翻还真的不知道)

结果

为了项目稳定,不再引发其他连锁反应,我没敢动 这个Mybatis的自动插入代码

就是实现了 MetaObjectHandler 接口的类,并实现了 insertFill(MetaObject metaObject) 方法 的这个 处理器 其实有一个解决办法,就是我一定要将将所有包含createTime 的实体类在 insert前,触发一次setCreateTime(LocalDateTime.now) 然后再insertFill中做一个判空,就可以解决这个问题,这就属于约定大于配置了。

但,为了防止其他问题,就只能,用setCrateBy(Security.getUserName())setCreateTime(LocalDateTime.now) 来委屈我疲惫的大猪蹄子了。

好像是第一次在掘金上发布文章,东西不难,不过场景很少见(毕竟是历史开发人员和新开发人员思维上的冲突),不过,还是希望后续有人避免遇见像我这样的bug,祝:各位看博文的朋友们都能遇见百万并发的项目

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论