文章目录
- 前言
- 问题回溯
- 排查过程
- 总结
前言
报错堆栈信息如下,基本是mybatis-plus源码中的一些东西:
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: java.lang.Object Not Found TableInfoCache.
at com.baomidou.mybatisplus.core.toolkit.ExceptionUtils.mpe(ExceptionUtils.java:49)
at com.baomidou.mybatisplus.core.toolkit.Assert.isTrue(Assert.java:38)
at com.baomidou.mybatisplus.core.toolkit.Assert.notNull(Assert.java:72)
at com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils.currentSessionFactory(GlobalConfigUtils.java:54)
at com.baomidou.mybatisplus.extension.toolkit.SqlHelper.sqlSessionFactory(SqlHelper.java:71)
at com.baomidou.mybatisplus.extension.toolkit.SqlHelper.executeBatch(SqlHelper.java:161)
at com.baomidou.mybatisplus.extension.toolkit.SqlHelper.executeBatch(SqlHelper.java:207)
at com.baomidou.mybatisplus.extension.service.impl.ServiceImpl.executeBatch(ServiceImpl.java:239)
at com.baomidou.mybatisplus.extension.service.impl.ServiceImpl.saveBatch(ServiceImpl.java:135)
at com.baomidou.mybatisplus.extension.service.IService.saveBatch(IService.java:73)
我这里的问题主要是,调用单个插入数据,是能插入成功的。调用批量时就会报错。
网上有些朋友说是因为实体定义,表名之类的问题。这个肯定不是我当前遇到的,否则单个插入数据也会报错。而且报错信息也会有所不同。
问题回溯
报错的地方是全局配置类中获取表信息的时候,取了个空:
可以看到此处的问题,传进来的clazz 居然成了 Object类型的。这就是问题的根本原因,压根没有一个表能对应上Object。
那么这个Object 是从哪来的呢?
排查过程
从堆栈信息入手,向前找,看看这个clazz 是谁传过来的。
终于,在源码中找到了。在mybatis-plus的service实现类中
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
批量方法:
再继续查找,这是当前实现类的属性值,应该是在对象初始化时,就赋值了。
这里是获取了父类的范型类型,看到这里,大概知道这个错误的原因了。就是这个类型,获取到的是Object类型,导致了后来的错误。
public static Class<?> getSuperClassGenericType(final Class<?> clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.warn(String.format("Warn: %s's superclass not ParameterizedType", clazz.getSimpleName()));
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.warn(String.format("Warn: Index: %s, Size of %s's Parameterized Type: %s .", index,
clazz.getSimpleName(), params.length));
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(String.format("Warn: %s not set the actual class on superclass generic parameter",
clazz.getSimpleName()));
return Object.class;
}
return (Class<?>) params[index];
}
一般来说,我们在写业务层时,会这样写:
public class UserService extends ServiceImpl<UserMapper, User> {
...
}
然后使用这个UserService就没有这个问题。
但是我现在这个会出这个问题,是因为在继承关系中,多加了一层
我目前使用的类,可以说是又继承了 UserService
,最关键的是UserService 并没有范型类型。因此直接返回了Object.class类型。
总结
在增加了继承关系的写法中,无法使用serviceImpl的一些方法。但是调用mapper的方法,是可以的。
这也就是为什么我的批量操作报错,单个插入却是可以成功的原因。
然后就是写这个层级结构时,可以将数据库相关的内容,全部写在 ServiceImpl 的直接子类中。其他地方再去调用。