不管是用MP2.X版本的还是MP3.X版本的小伙伴都会发现,在其IService接口中 并没有一个可以直接获取一条记录的方法。
@Override
public T selectOne(Wrapper<T> wrapper){
return SqlHelper.getObject(baseMapper.selectList(wrapper));
}
查询多条记录,如果存在则返回List.get(0)位置上的数据。
T getOne(Wrapper<T> queryWrapper,boolean throwEx){
return throwEx?this.baseMapper.selectOne(queryWrapper):SqlHelper.getObject(this.log,this.baseMapper.selectList(queryWrapper));
}
getOne方法只不过是在2.x的selectOne方法上多了一个布尔值,意思就是如果为true,则就是查询多条记录就会抛异常,如果为false,则查询多条记录后,取get(0)第一个位置记录返回。
不难看出,不管是selectOne还是getOne 底层调用的是selectList,有些人会说了,正常情况下,自己调用selectOne的数据,基本也是唯一。 但是在有些情况下,通过selectOne调用再由selectList的一些sql获取到的结果其实是多条甚至是成百上千条(有时候真的会遇到),可是你只会看到第一条数据。虽然说业务上并不会影响你们,但是你想过没有,如果稍有不慎你的sql查询的结果在数据库里是10000条,而这个查询经常被调用,也就是说10000条数据返回被加载在内存,然后就给了你一条,你是爽了,服务器有负担了。所以我们需要一个在sql语句阶段就能限制查询一条的结果的东西,那毋庸置疑就是LIMIT 1,那如何使用LIMIT 1 有以下两种常用写法。
mapper.xml中写一个关于本次查询的sql ,尾部加上 limit 1
SELECT
colum1,colum2,colum3
FROM
table1
WHERE
条件
LIMIT 1
这种写法有一个不好的地方在哪里呢,对于单表查询来说的话,不友善,几乎你条件一变,要么你用if标签,要么你就得再写一次sql语句。反正个人就觉得挺丑的。
在MP提供的 Wrapper接口的实现类中都存在一个 last方法 用来最后拼接一个sql片段,在这里我们加一个limit 1。
public Children last(boolean condition, String lastSql) {
if (condition) {
this.lastSql.setStringValue(" " + lastSql);
}
return this.typedThis;
}
日常开发的时候基本就这么写
2.x写法
xxService.selectOne(new EntityWrapper().eq().eq().last("limit 1"));
3.x写法
xxService.selectOne(new QueryWrapper().eq().eq().last("limit 1"));
但是这也有一个挺恶心人的地方,就是这last放这 加上 limit 1 还是魔法值,挺难看的。所以可以变成以下封装。
你创建Service接口的时候一定会集成MP中的IService接口,所以就在这里利用java 8的新特性(接口的默认实现方法)来完成封装.
这里的xxx指的是你业务中的某个实体类,懂的都懂。
2.x写法
public interface xxxService extends IService<xxx>{
/**
* 仅有一条数据
* @param wrapper
* @return
*/
default xxx getOnly(EntityWrapper<xxx> wrapper){
wrapper.last("limit 1");
return this.selectOne(wrapper);
};
}
3.x写法
public interface xxxService extends IService<xxx>{
/**
* 仅有一条数据
* @param wrapper
* @return
*/
default xxx getOnly(QueryWrapper<xxx> wrapper){
wrapper.last("limit 1");
return this.getOne(wrapper);
};
}
这样,你就可以将代码中的selectOne方法 无缝替换了。