- 0. 接口结构:
- 1. 方法报错:
- 2. 解决方法:
- 3. 原因分析:
0. 接口结构:
【接口】:
public interface PurchaseOrderService extends IService<PurchaseOrder> {}
【接口实现类】:
public class PurchaseOrderServiceImpl extends BasePurchaseOrderService implements PurchaseOrderService {}
【实现类基类】
abstract class BasePurchaseOrderService extends ServiceImpl<PurchaseOrderMapper, PurchaseOrder> {}
结构:不同类型的订单会有不同是实现类,对于一些公共的操作,会在基类中实现
1. 方法报错:
- 当执行Mybatis-Plus的
ServiceImpl
一些方法,比如updateBatchById、saveBatch等
时- 便会报错:
Not Found TableInfoCache
2. 解决方法:
- 修改接口结构,基类使用<M,T>泛型,M:Mapper类;T:对应的Model类
【接口实现类】:
public class PurchaseOrderServiceImpl extends BasePurchaseOrderService<PurchaseOrderMapper, PurchaseOrder> implements PurchaseOrderService {}
【实现类基类】
abstract class BasePurchaseOrderService<M extends BaseMapper<T>, T> extends ServiceImpl<PurchaseOrderMapper, PurchaseOrder> {}
- 此外,还有一种解决方法,参考连接:https://github.com/baomidou/mybatis-plus/issues/578
- 就是重写ServiceImpl的currentModelClass方法和currentMapperClass方法
abstract class BasePurchaseOrderService extends ServiceImpl<PurchaseOrderMapper, PurchaseOrder> implements BaseService<PurchaseOrder> {
@Override
protected Class<PurchaseOrder> currentModelClass() {
return (Class<PurchaseOrder>) GenericTypeResolver.resolveTypeArgument(getClass(), BaseService.class);
}
// currentMapperClass的重写方法不知道怎么实现... ...
}
public interface BaseService<T> extends IService<T>{}
3. 原因分析:
- 以
updateBatchById
来,调用链路:- executeBatch ➡ sqlSessionFactory ➡ currentSessionFactory ➡ getTableInfo
/**
* IService 实现类( 泛型:M 是 mapper 对象,T 是实体 )
*
* @author hubin
* @since 2018-06-23
*/
@SuppressWarnings("unchecked")
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
protected Class<T> entityClass = currentModelClass();
protected Class<T> mapperClass = currentMapperClass();
/**
* 执行批量操作
*
* @param consumer consumer
* @since 3.3.0
* @deprecated 3.3.1 后面我打算移除掉 {@link #executeBatch(Collection, int, BiConsumer)} }.
*/
@Deprecated
protected boolean executeBatch(Consumer<SqlSession> consumer) {
return SqlHelper.executeBatch(this.entityClass, this.log, consumer);
}
- 显然:getTableInfo获取为null才报的错,从报错也知道,此时的class 为
java.lang.Object
- 显然获取的class不对,而class就是ServiceImpl的entityClass
- 默认下,entityClass取的父类的第2个泛型参数,mapperClass取的父类的第1个泛型参数
- 也就是说,像本例多继承的情况下,由于父类BasePurchaseOrderService没有泛型参数
- 对于currentModelClass方法,最终获取了
java.lang.Object
- 最终报错了
public class PurchaseOrderServiceImpl extends BasePurchaseOrderService implements PurchaseOrderService {}
- 所以解决方法就很容易理解,给继承的父类方法加上对应的<M,T>泛型参数即可
- 或者重写对应的方法,让其返回正确的entityClass,mapperClass
- 正常没有多继承的情况,是不是就没问题,其父类ServiceImpl有泛型参数
- mapperClass 为PurchaseOrderMapper;entityClass为PurchaseOrder
public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, PurchaseOrder> implements PurchaseOrderService {}
- 另外提一下,mapperClass用于获取sqlStatement
- String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID);
- 最终:sqlStatement = mapper.getName() + StringPool.DOT + sqlMethod.getMethod();
- 而sqlStatement用于获取最终的语句执行,不正确的sqlStatement最终获执行报错