![e6e4b4e2a601c0a20026a0f4af8491c7.png](https://i-blog.csdnimg.cn/blog_migrate/15a824d3db075a837c4bf3466914fc0a.jpeg)
Mybatis Plus 实现分页查询的两种方法
我们使用Mybatis Plus实现分页查询有两种方式,一种是使用自带的查询方法实现分页查询,另一种就是自定义查询然后分页。
不管哪种方式进行分页,要实现分页,首先都需要将Mybatis Plus的分页插件定义好,然后就可以直接应用分页查询了。
新建分页插件
package com.itzhimei.mybatis.plus;import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;import org.mybatis.spring.annotation.MapperScan;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.transaction.annotation.EnableTransactionManagement;@EnableTransactionManagement@Configuration@MapperScan("com.itzhimei.mybatis.plus.mapper*")public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 开启 count 的 join 优化,只针对部分 left join paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); return paginationInterceptor; }}
使用自带的查询方法实现分页查询
@Test public void testSelectPage() { System.out.println(("----- selectAll method test ------")); Page userPage = userMapper.selectPage(new Page(1, 2), null); List records = userPage.getRecords(); records.forEach(System.out::println); }
Mybatis Plus 自带的分页方法selectPage,需要传入一个Page类型的对象,用于配置分页信息,第二个参数是配置查询条件,我们这里没有查询条件所以set为null。
Mybatis Plus自带两种分页方法:
/** * 根据 entity 条件,查询全部记录(并翻页) * * @param page 分页查询条件(可以为 RowBounds.DEFAULT) * @param queryWrapper 实体对象封装操作类(可以为 null) */ > E selectPage(E page, @Param(Constants.WRAPPER) Wrapper queryWrapper); /** * 根据 Wrapper 条件,查询全部记录(并翻页) * * @param page 分页查询条件 * @param queryWrapper 实体对象封装操作类 */ >> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper queryWrapper);
区别是:selectPage返回的是对象,selectMapsPage返回的是key-value的map。
输出结果:
==> Preparing: SELECT COUNT(1) FROM user ==> Parameters: <== Columns: COUNT(*)<== Row: 5==> Preparing: SELECT id,name,age,email FROM user limit ? ==> Parameters: 2(Long)<== Columns: ID, NAME, AGE, EMAIL<== Row: 1, Jone, 18, test1@baomidou.com<== Row: 2, Jack, 20, test2@baomidou.com<== Total: 2
上面是打印的日志,从日志可以看出,Mybatis Plus执行了两个sql,一个是统计总记录的sql,一个是查询结果集的sql。
自定义查询然后分页
我们自定义的分页查询其实和这个写法类似。
1、在Classz的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 { /** * 关联查询 * @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 selectClassAndStudentsForPage(IPage page);}
这个查询方法的参数就是IPage page,我这里没有使用泛型,因为我只需要用page的最基本的功能,就是当前页码、每页记录数、总记录数、总页数等这些和分页相关的参数。
这样定义的方法,能够让我即自定义查询,又带有分页,且代码量也并不多,重要是得简单且灵活。
2、定义结果eneity:ClasszAndStudent
import lombok.Data;/** * @Auther: www.itzhimei.com * @Description: 班级和学生entity */@Datapublic class ClasszAndStudent { private Long id; private String name; private Long stdId; private Long cid; private String stdName;}
3、测试
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)@SpringBootTestpublic class ClassStudentTest { @Autowired private ClasszMapper classzMapper; @Test public void testSelectPage() { IPage page =new Page(1, 1); List 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(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 selectClassAndStudentsForPage(IPage page, ClassCondition condition);
这里的ClassCondition condition,就可以作为一个参数实体,拼装条件。
上面demo中mapper的方法,是返回的List,你可能会问,page信息怎么返回,办法就是在Service层来处理。
@Autowired ClasszMapper classzMapper; public IPage selectClassAndStudentsForPage(Page page, ClassCondition condition) { IPage result = new Page<>(); List list = classzMapper.selectClassAndStudentsForPage(page, condition); result.setRecords(list); return result; }
这就是分页结果的返回方式,这里其实和第二节的使用方式是一样的,都是返回的是IPage对象,只是这里是手动赋值。