一、背景
今天一个线上问题报错如下:
org.apache.ibatis.exceptions.TooManyResultsException:
Expected one result (or null) to be returned by selectOne(), but found: 2
通过报错信息可以知道这个是一个数据查询结果集不符的问题,程序中预期是只有一条数据的,但是查出来的结果有多个。
二、问题排查
① 先看数据:提取出来SQL语句执行发现真的是有2条符合记录
② 那就是SQL语句的编写有问题,定位SQL语句产生的那一行代码
③ 发现使用了MyBatisPlus的LambdaQuery()查询中的one()方法
PS: 这里贴一下出错的代码行
BHOrderCargoSizeEntity splitCargoSize =
bhOrderCargoSizeService.lambdaQuery().eq(BHOrderCargoSizeEntity::getSplitId,x.getId()).one();
三、问题深究
3.1、selectOne()第一印象
可能对于多数人one()方法给人的第一印象是:取查询结果的其中一个然后返回
3.2、真正的selectOne()
既然都已经产生的错误那selectOne()的实际操作肯定不是和上面的想的一样的。我们点进去MP的源码可以看到如下:
① 先点击去One()方法可以看到如下:
// 这里是MyBatisPlus源码
/**
* 获取单个
*
* @return 单个
*/
default T one() {
return getBaseMapper().selectOne(getWrapper());
}
Java
Copy
② 这里可以看到是调用了selectOne()方法,同样我们在使用条件构造器进行查询时:
// 日常项目中构造器查询代码示例
@Override
public UserEntity queryByMobile(String mobile) {
return baseMapper.selectOne(new QueryWrapper<UserEntity>().eq("mobile", mobile));
}
Java
Copy
其中的selectOne()操作也是单条数据查询的。
于是我们找到如下部分代码:
// 这里是MyBatisPlus源码
@Override
public T getOne(Wrapper<T> queryWrapper, boolean throwEx) {
if (throwEx) {
return baseMapper.selectOne(queryWrapper);
}
return SqlHelper.getObject(baseMapper.selectList(queryWrapper));
}
Java
Copy
我们可以发现:
。有异常抛给上层处理
。正常情况下getOne()的操作是selectList()实现的
③ 当有多条数据时就有了如下的情况:
// 这里是MyBatisPlus源码
/**
* <p>
* 从list中取第一条数据返回对应List中泛型的单个结果
* </p>
*
* @param list
* @param <E>
* @return
*/
public static <E> E getObject(List<E> list) {
if (CollectionUtils.isNotEmpty(list)) {
int size = list.size();
if (size > 1) {
logger.warn(String.format("Warn: execute Method There are %s results.", size));
}
return list.get(0);
}
return null;
}
Java
Copy
④ 通过上述表明:
。当只有一条数据返回时程序能正常执行
。当数据返回多条时就会给出异常提示了
四、问题解决
① 直接使用MyBatisPlus的last方法在sql末尾追加语句“limit 1”,代码如下:
BHOrderCargoSizeEntity splitCargoSize =
bhOrderCargoSizeService.lambdaQuery().eq(BHOrderCargoSizeEntity::getSplitId,x.getId()).last("limit 1").one();
② 网上有一些重写selectOne方法的,基本通过重写或切面编程。有兴趣可以了解下(不建议新手这样操作!)
PS:关于MyBatisPlus的语法知识点也可以参考我之前的文章:
初见MyBatisPlus
五、后记
遇到问题知道怎么解决是不够的,能追其本质才是乐趣所在。
更多精彩内容,欢迎持续关注:光华技术
本文暂时没有评论,来添加一个吧(●'◡'●)