使用MybatisPlus的lambdaQuery().one()查询时,如果查询结果不存在,那么就会报错:
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Class must not be null
at com.baomidou.mybatisplus.core.toolkit.ExceptionUtils.mpe(ExceptionUtils.java:49) ~[mybatis-plus-core-3.5.3.jar:3.5.3]
at com.baomidou.mybatisplus.core.toolkit.Assert.isTrue(Assert.java:38) ~[mybatis-plus-core-3.5.3.jar:3.5.3]
at com.baomidou.mybatisplus.core.toolkit.Assert.notNull(Assert.java:72) ~[mybatis-plus-core-3.5.3.jar:3.5.3]
at com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils.currentSessionFactory(GlobalConfigUtils.java:53) ~[mybatis-plus-core-3.5.3.jar:3.5.3]
at com.baomidou.mybatisplus.extension.toolkit.SqlHelper.sqlSession(SqlHelper.java:86) ~[mybatis-plus-extension-3.5.3.jar:3.5.3]
at com.baomidou.mybatisplus.extension.toolkit.SqlHelper.execute(SqlHelper.java:301) ~[mybatis-plus-extension-3.5.3.jar:3.5.3]
解决办法
将mybatis-plus-boot-starter版本升级到3.5.3.1
原因
IService接口的lambdaQuery()方法构建一个LambdaQueryChainWrapper类的实现对象并返回用于后面的链式调用,而这里构建LambdaQueryChainWrapper类对象时使用的是LambdaQueryChainWrapper(BaseMapper<T> baseMapper, Class<T> entityClass)这个构造方法,这个方法并没有给当前类的成员变量entityClass赋值:
public LambdaQueryChainWrapper(BaseMapper<T> baseMapper, Class<T> entityClass) {
super();
this.baseMapper = baseMapper;
super.wrapperChildren = new LambdaQueryWrapper<>(entityClass);
}
接下来看链式调用的one()方法,这个方法会执行ChainWrapper接口的默认方法execute(SFunction<BaseMapper<T>, R> function),这个方法在执行传入进来的function函数,这个函数就是mapper.selectOne(getWrapper()),当这个函数执行的结果为null时,这里就会执行orElseGet后面的部分:
default <R> R execute(SFunction<BaseMapper<T>, R> function) {
return Optional.ofNullable(getBaseMapper()).map(function).orElseGet(() -> SqlHelper.execute(getEntityClass(), function));
}
而在后面这个部分中会执行getEntityClass()这个函数,在这里这个函数的实现是由LambdaQueryChainWrapper类来实现的:
@Override
public Class<T> getEntityClass() {
return entityClass;
}
可以看到这个实现就是直接返回了LambdaQueryChainWrapper类的成员变量entityClass,而这个变量在我们前面讲到的构建LambdaQueryChainWrapper类对象过程中是没有赋值的,所以导致后面在使用这个值时报了MybatisPlusException: Class must not be null异常,而在3.5.3.1版本中LambdaQueryChainWrapper类的getEntityClass()函数返回的是super.wrapperChildren.getEntityClass():
@Override
public Class<T> getEntityClass() {
return super.wrapperChildren.getEntityClass();
}