不管是用MP2.X版本的还是MP3.X版本的小伙伴都会发现,在其IService接口中 并没有一个可以直接获取一条记录的方法。

MP2.x提供selectOne方法
@Override
public T selectOne(Wrapper<T> wrapper){
    return SqlHelper.getObject(baseMapper.selectList(wrapper));
}

查询多条记录,如果存在则返回List.get(0)位置上的数据。

MP3.x提供getOne方法
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方法 无缝替换了。