今天有了一个需求,就是对连表查询的sql语句进行分页操作,我们都知道MP中的BaseMapper自带的方法都是对单表进行的操作,那么selectPage等分页查询方法自然也不例外。这个时候我就在想,要不然自己在sql语句中加入limit来进行分页算了,但是又想到自己页面中的部分其他功能又依赖于MP中的Page对象,那我要为了这个功能手搓一个自己的Page对象?nonono!too troublesome!
于是我就开始了我的搜索引擎大法,然后就发现其实还是有一种很简单的办法的,就是按照selectMapsPage方法,写一个自己的分页方法,这样就可以实现我的需求了。PS:你想写一个自己的selectPage方法也是可以,这里我的需求是要写一个自己的selectMapsPage方法。
前置条件和需求:
有一个phone表和user表,与之对应的是Phone类和User类。Phone是手机,User是用户,uid代表用户id,uname代表用户的名字
Parking类的属性:id,pname,uid(对应User表中的id)
User类的属性:id,uname
需求就是 连表查询出 id,pname,uid,uname四个字段,并封装在Map对象中,用于在HTML中显示,手机属于谁。
实现需求方案:
// MP中BaseMapper自带的方法
<P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 在Mapper中根据需求模仿出来的方法,这里为了看起来清晰,就使用了@Select注解,不了解的自行查一下
@Select("select
p.id id,p.pname pname,p.uid uid,u.uname uname
from `phone` p left join `user` u on p.uid = u.id")
IPage<Map<String,Object>> selectMyMapsPage(Page<Map<String,Object>> page ,@Param(Constants.WRAPPER) Wrapper<Map<String,Object>> queryWrapper);
Service和Controller中的方法:
Service:
@Override
public Page<Map<String, Object>> getMyMapsPage(Long pageNum, Long pageSize) {
Page<Map<String,Object>> parkingPage = new Page<>(pageNum, pageSize);
// 分页后的数据会赋值给parkingPage,也会return出来,所以怎么用都可以
return (Page<Map<String, Object>>) baseMapper.selectMyPage(parkingPage,null);
}
Controller:
@RequestMapping("/getMapsPage")
// 因为Page类没有重写toString()方法,所以这里为了直观,返回查询出来的分页数据。
public List<Map<String, Object>> getMapsPage(Long pageNum,Long pageSize){
Page<Map<String, Object>> page = MyService.getPage(pageNum, pageSize);
return page.getRecords();
}
发起请求:/getMapsPage?pageNum=1&pageSize=2
结果:
[{pname='iphone6s', id=1, uid=1 ,uname='小明'}, {pname='RedmiK40', id=2, uid=2 ,uname='小红'}]
到这里,其实已经算是解决完问题了,如果你是使用在Thymeleaf渲染HTML的情况下,我这里还有几个注意事项要告诉你。
注意事项:
1、使用 selectMapsPage 某个字段的返回值是null,那么这一条记录对应的map中,就不会有这个字段。
2、使用 selectMapsPage 要注意封装到map里的key是原封不动的,不会像封装到对象里时,会适配驼峰命名规则
3、在Thymeleaf语法中,对map对象,推荐使用map[key]的方式获取值,而不要使用map.key获取,
因为当key不存在的时候,map[key]返回的是null(在不拼接字符串的情况下,显示为空字符串),不会报错,而map.key会报错