快捷搜索: 王者荣耀 脱发

mybatis-plus 包引用踩坑

开发过程经常使用mybatis-plus插件对mybatis进行增强操作,它对mybatis的一般操作做了一层封装,使用起来简单快捷

但是,往往也隐藏着风险。今天就有一个问题,导致自己查找了好久,最后发现是引用包的问题导致。。。

问题现象:

保存操作,执行成功数据库返回data为插入数据返回id,但是这个id一看就是未指定自增情况先导致的。

首先,排查数据库,数据库表主键是否设置自增:

数据库没有勾上自增,勾上,执行命令truncate table xxxx;

再查看entity定义:

mybatis-plus生成代码未指定type,加上type=IdType.AUTO

再次执行新增操作:

依然有问题

然后,就开启了漫长的探索之路:

跟踪源码 saveOrUpdate:

@Transactional(
    rollbackFor = {Exception.class}
)
public boolean saveOrUpdate(T entity) {
    if (null == entity) {
        return false;
    } else {
        Class<?> cls = entity.getClass();
        TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
        Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
        String keyProperty = tableInfo.getKeyProperty();
        Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
        Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
        return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
    }
}

打断点第9行,发现这个tableInfo中的idType类型是ASSIGN_ID

这放谁受得了,直接跟进getTableInfo去看看,为啥会是这个样子。

public static TableInfo getTableInfo(Class<?> clazz) {
    if (clazz != null && !ReflectionKit.isPrimitiveOrWrapper(clazz) && clazz != String.class) {
        TableInfo tableInfo = (TableInfo)TABLE_INFO_CACHE.get(ClassUtils.getUserClass(clazz));
        if (null != tableInfo) {
            return tableInfo;
        } else {
            for(Class currentClass = clazz; null == tableInfo && Object.class != currentClass; tableInfo = (TableInfo)TABLE_INFO_CACHE.get(ClassUtils.getUserClass(currentClass))) {
                currentClass = currentClass.getSuperclass();
            }

            if (tableInfo != null) {
                TABLE_INFO_CACHE.put(ClassUtils.getUserClass(clazz), tableInfo);
            }

            return tableInfo;
        }
    } else {
        return null;
    }
}

发现这个玩意儿是个缓存,然后重新编译重启应用--不行 ---> 删表--建表--不行;来来回回搞了几次。扛不住了,搞崩溃了,唯一的成就就是排除了数据库的嫌疑,那么问题肯定出现在代码层面。然后,蓦然回首,发现之前多次试验发现那个idType一直稳如老狗,不论我怎么改,它一直是ASSIGN_ID。我赶紧去看了下IdType的源码,如下:

我去,这个里面没这个ASSIGN_ID类型!!!

那么,问题来了,我运行时加载的这个类型从哪儿来的呢,它毫无疑问,肯定是个默认值,难道是我引用包的问题?

赶紧滚去看下正常的entity里面引用的IdType包的,是下图这个样子的:

对比下自己的

哦豁!!!终于找到问题原因了。看下这个annotations包下面的IdType:

里面有那个万恶的ASSIGN_ID了

修改引用包类型,重启应用(别忘了数据库执行truncate table xxxx),新增数据:

bingo,好了!!!

延伸:

1、这次问题查找,如果没有参考的那么,这个问题突破点还是在那个IdType这个类型上,应该点进去看下这个IdType在源码中用的是哪个包下的:

看着没,这里已经很明显的发现问题了。

2、我在其他工程也发现其他的使用方式,如下图所示:

这个与我使用的方式是怎么不一样的?都是苞米豆的,为啥会存在这两种方式?等着以后探索。。。

经验分享 程序员 微信小程序 职场和发展