在前面的章节已经演示过基于Mybatis Plus自带的查询方法实现分页查询,但是有时候如果我的查询特别复杂,要自己写sql,类似于mybatis在xml中写sql,这时该如何分页呢,我们这一节就来演示一下。
我们先来回顾一下在第二节使用的分页方式。
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
这个方法是基于生成的mapper,掉用selectPage方法,并传入条件参数,来完成查询。
我们自定义的分页查询其实和这个写法类似。
1、在Classz的mapper中,定义一个联查方法
package com.itzhimei.mybatis.plus.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.itzhimei.mybatis.plus.model.Classz;
import com.itzhimei.mybatis.plus.model.ClasszAndStudent;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @Auther: www.itzhimei.com
* @Description:
*/
public interface ClasszMapper extends BaseMapper<Classz> {
/**
* 关联查询
* @return
*/
@Select("select a.*,b.id stdId,b.cid, b.name stdName from classz a ,student b where a.id = b.cid and a.id = 1")
List<ClasszAndStudent> selectClassAndStudentsForPage(IPage page);
}
这个查询方法的惨呼就是IPage page,我这里没有使用泛型,因为我只需要用page的最基本的功能,就是当前页码、每页记录数、总记录数、总页数等这些和分页相关的参数。
这样定义的方法,能够让我即自定义查询,又带有分页,且代码量也并不多。
2、定义结果eneity:ClasszAndStudent
package com.itzhimei.mybatis.plus.model;
import lombok.Data;
/**
* @Auther: www.itzhimei.com
* @Description: 班级和学生entity
*/
@Data
public class ClasszAndStudent {
private Long id;
private String name;
private Long stdId;
private Long cid;
private String stdName;
}
3、测试
package com.itzhimei.mybatis.plus.test;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itzhimei.mybatis.plus.mapper.ClasszMapper;
import com.itzhimei.mybatis.plus.mapper.StudentMapper;
import com.itzhimei.mybatis.plus.model.ClasszAndStudent;
import com.itzhimei.mybatis.plus.model.Student;
import com.itzhimei.mybatis.plus.model.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
/**
* @Auther: www.itzhimei.com
* @Description:
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ClassStudentTest {
@Autowired
private ClasszMapper classzMapper;
@Test
public void testSelectPage() {
IPage page =new Page<User>(1, 1);
List<ClasszAndStudent> classzs = classzMapper.selectClassAndStudentsForPage(page);
classzs.forEach(System.out::println);
}
}
在测试方法中,我定义了分页对象Page,设置了页码和每页数据条数,demo中设置的是第一页的一条记录。
4、输出
==> Preparing: SELECT COUNT(1) FROM classz a, student b WHERE a.id = b.cid AND a.id = 1
==> Parameters:
<== Columns: COUNT(*)
<== Row: 2
==> Preparing: select a.*,b.id stdId,b.cid, b.name stdName from classz a ,student b where a.id = b.cid and a.id = 1 limit ?
==> Parameters: 1(Long)
<== Columns: ID, NAME, STDID, CID, STDNAME
<== Row: 1, 一年一班, 1, 1, 小明
<== Total: 1
我们从日志输出可以看出,总记录2条,当前查询了一条。
我手动完成一个翻页,也就是继续查询第二页数据,demo中的page做一些修改。
IPage page =new Page<User>(2, 1);
输出
==> Preparing: SELECT COUNT(1) FROM classz a, student b WHERE a.id = b.cid AND a.id = 1
==> Parameters:
<== Columns: COUNT(*)
<== Row: 2
==> Preparing: select a.*,b.id stdId,b.cid, b.name stdName from classz a ,student b where a.id = b.cid and a.id = 1 limit ? offset ?
==> Parameters: 1(Long), 1(Long)
<== Columns: ID, NAME, STDID, CID, STDNAME
<== Row: 1, 一年一班, 2, 1, 小欧
<== Total: 1
这里可以看到结果从“小明”变为了“小欧”,分页成功。
补充:
如果自定义查询有条件怎么办?
也很简单,在mapper定义的方法中再添加一个参数,例如:
List<ClasszAndStudent> selectClassAndStudentsForPage(IPage page, ClassCondition condition);
这里的ClassCondition condition,就可以作为一个参数实体,拼装条件。
上面demo中mapper的方法,是返回的List<实体>,你可能会问,page信息怎么返回,办法就是在Service层来处理。
@Autowired
ClasszMapper classzMapper;
public IPage<ClasszAndStudent> selectClassAndStudentsForPage(Page page, ClassCondition condition) {
IPage<ClasszAndStudent> result = new Page<>();
List<ClasszAndStudent> list = classzMapper.selectClassAndStudentsForPage(page, condition);
result.setRecords(list);
return result;
}
这就是分页结果的返回方式,这里其实和第二节的使用方式是一样的,都是返回的是IPage<实体>对象,只是这里是手动赋值。