赞
踩
最近在项目中遇到个比较奇怪的问题,使用QueryWrapper查询一条数据时,如果表中有大于1条命中,则会报:org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2 异常。
代码如下:
QueryWrapper<Crm> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(Crm::getShopId, cdtShopId)
.orderByDesc(Crm::getId).last(" limit 1");
return baseMapper.selectOne(queryWrapper);
照常说上面代码会变成下面的sql
SELECT * FROM crm WHERE shopId = ? ORDER BY id DESC limit 1
但实际上跑出来的结果是没有加上最后的limit 1
经过不断测试得知:使用QueryWrapper的lambda()方法时,会new一个LambdaQueryWrapper返回,这时候直接在eq()、orderByDesc()后面使用last()并不会把last()中的sql拼接到sql后面
public LambdaQueryWrapper<T> lambda() {
return new LambdaQueryWrapper<>(entity, entityClass, sqlSelect, paramNameSeq, paramNameValuePairs, expression);
}
原因有可能是下图所示,last()使用的是LambdaQueryWrapper的last,而selectOne()使用的是QueryWrapper对象分开写,具体原因还在查,后续再加上
分开写后的last()是QueryWrapper
解决这个问题有几个办法
1.last()不直接在eq()、orderByDesc()后面使用,继续使用QueryWrapper的last():
QueryWrapper<Crm> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(Crm::getShopId, cdtShopId)
.orderByDesc(Crm::getId);
queryWrapper.last(" limit 1");
return baseMapper.selectOne(queryWrapper);
2.QueryWrapper不使用lambda:
QueryWrapper<Crm> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("shopId", cdtShopId)
.orderByDesc("Id").last(" limit 1");
return baseMapper.selectOne(queryWrapper);
3.直接使用LambdaQueryWrapper:
LambdaQueryWrapper<Crm> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Crm::getShopId, cdtShopId)
.orderByDesc(Crm::getId).last(" limit 1");
return baseMapper.selectOne(queryWrapper);
以上三种方法都可
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。