MyBatis的几种分页方式,你学"废"了么🌚

3,411 阅读5分钟

分页查询

分页查询可以分为前端分页后端分页,前端分页是指后端直接把数据库表的所有数据响应给前端,由前端进行分页显示, 该方式如果造数据量比较大的情况下,对内存和网络传输的消费非常大。而后端分页是指,前端发起分页请求,将相关的分页数据发送给后端(如pageNum,PageSize等),后端根据分页的相关数据将分页后的数据返回给前端,从而实现分页,一般都是采用后端分页。

MyBatis分页

MyBatis的分页方式有物理分页和逻辑分页,所谓物理分页是指直接从数据库中拿出我们需要的数据,例如在Mysql中使用limit。而逻辑分页是指从数据库中拿出所有符合要求的数据,然后再从这些数据中拿到我们需要的分页数据。

物理分页

采用limit分页(物理分页)

MySQL提供的limit关键字可以帮助我们返回我们查询的指定前几行或者中间某几行数据,因此他也可以应用于我们的分页中,使用Limit需要给定1个或2个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目,例如limit 0,4表示返回第1行到第4行,总共4行的数据,放到分页中就表示,返回第一页中的4行数据,如要返回第二页的4行数据那么就是limit 4,4,第三页就是limit 8,4,用公式表示就是limit (pageNum-1)*pageSize , pageSize [pageNum表示取第几页的数据,pageSize表示每一页中的数据数量]。如果只指定一个参数则表示返回最大的记录行数目,例如limit 10,其等同于limit 0,10,表示返回第1行到第10行的10行数据。

使用过程

  • 表数据

image.png

  • 实体类
@Data
public class User {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
}
  • SQL语句
<select id="listUser" resultMap="BaseResultMap">
    select * from user
    <if test="pageNum!=null and pageSize!=null">
        limit #{pageNum},#{pageSize}
    </if>
</select>
  • Mapper方法
List<User> listUser(Integer pageNum,Integer pageSize);
  • 测试,取出第一页的4条数据
@Test
void contextLoads() {
    //查询出第页
    List<User> users = userDao.listUser(0, 4);
    for (User user : users) {
        System.out.println(user.toString());
    }
}
  • 查询结果

image.png

  • 测试,取出第二页的4条数据
@Test
void contextLoads() {
    //查询出第页
    List<User> users = userDao.listUser(4, 4);
    for (User user : users) {
        System.out.println(user.toString());
    }
}
  • 查询结果

image.png

使用PageHelper分页插件(物理分页)

使用过程

  • pom文件中引入PageHelper依赖
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.3</version>
</dependency>
  • SQL语句
<!--pageHelper-->
<select id="listUser2" resultMap="BaseResultMap">
    select * from user
</select>
  • Mapper方法
List<User> listUser2();
  • 测试,取出第一页的4行数据,其中PageHelper.startPage()方法用于开启分页,通过拦截SQL的方式(只要再该方法后面执行的SQL都会被拦截),把查询语句拦截下来加上limit。
@Test
void test2() {
    //pageNum为前端传递过来的分页后的“当前处在第几页”,默认在第一页
    int pageNum=1;
    //pageSize,表示每页存放的记录数
    int pageSize=4;
    PageHelper.startPage(pageNum,pageSize);
    List<User> users = userDao.listUser2();
    //得到分页对象
    PageInfo<User> page = new PageInfo<>(users);
    for (User user : page.getList()) {
        System.out.println(user.toString());
    }
}
  • 查询结果

image.png

  • 测试,取出第二页的4行数据
@Test
void test2() {
    //pageNum为前端传递过来的分页后的“当前处在第几页”,默认在第一页
    int pageNum=2;
    //pageSize,表示每页存放的记录数
    int pageSize=4;
    PageHelper.startPage(pageNum,pageSize);
    List<User> users = userDao.listUser2();
    //得到分页对象
    PageInfo<User> page = new PageInfo<>(users);
    for (User user : page.getList()) {
        System.out.println(user.toString());
    }
}
  • 查询结果

image.png

MyBatis Plus分页

MyBatisPls分页是基于 MyBatis的物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询。

使用步骤

  • SpringBoot引入MyBatis-plus依赖
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.2</version>
</dependency>
  • 配置yml配置文件
spring:
  #配置数据源
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/students?serverTimezone = Asia/Shanghai
    username: root
    password: root


# Mybatis-plus配置
mybatis-plus:
  mapper-locations: classpath*:/mapper/*Mapper.xml
  # 配置mybatis数据返回类型别名
  type-aliases-package: com.example.mp.pojo
  configuration:
    # 自动驼峰命名
    map-underscore-to-camel-case: false

# 配置sql打印,指向mapper的包
logging:
  level:
    com.example.mp.mapper: debug
server:
  port: 8081
  • 配置PaginationInterceptor分页拦截器组件
@Configuration
public class MyBatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}
  • 定义Mapper接口
public interface UserMapper extends BaseMapper<User> {
}
  • 测试,获取第一页的数据,每页4行数据(🚨注意:这里的Page中的current表示的是当前的页码,起始页码为1,size表示每页的数据量)

image.png

  • 查询结果

image.png

自定义分页

上面我们的Mapper接口方法并没有定义任何方法,我们使用的是MyBatisPlus提供的分页方法selectPage(Page page ,QueryWrapper queryWrapper),下面我们使用自定义的分页方法。

  • Mapper接口方法
public interface UserMapper extends BaseMapper<User> {

    IPage<User> slefPageUser(Page<User> page, User user);
}
  • SQL语句
<select id="slefPageUser" resultMap="BaseResultMap">
    select * from user
    <where>
        <if test="user!=null and user.username!=null">
            and username=#{user.username}
        </if>

        <if test="user!=null and user.address!=null">
            and address=#{user.address}
        </if>

        <if test="user!=null and user.birthday!=null">
            and birthday=#{user.birthday}
        </if>

        <if test="user!=null and user.sex!=null">
            and sex=#{user.sex}
        </if>


    </where>
</select>
  • 测试,查询第一页中,username爱喝奶茶的Programmer的User
Page<User> page = new Page<>(1, 4);
User user = new User();
user1.setUsername("爱喝奶茶的Programmer");
IPage<User> userPage = userMapper.slefPageUser(page,user);
List<User> users = userPage.getRecords();
for (User u : users) {
    System.out.println(u.toString());
}
  • 查询结果

image.png

逻辑分页

RowBounds分页(逻辑分页)

RowBounds分页属于逻辑分页,即实际上SQL查询的是所有的数据,然后在业务层对数据进行可截取(即对ResultSet结果集进行分页),该方式比较占用内存,在大数据量的情况下不推荐使用!

  • RowBounds对象有2个属性,offsetlimitoffset表示起始行数,limit表示需要的数据行数,他们结合起来就表示从第offset+1行开始,取limit行的数据。

使用过程

  • SQL语句
<!--RowBounds-->
<select id="listUser3" resultMap="BaseResultMap">
    select * from user
</select>
  • Mapper方法
List<User> listUser3(RowBounds rowbouns);
  • 测试,取第一页的4行数据
@Test
void test3() {
    RowBounds rowBounds = new RowBounds(0, 4);
    List<User> users = userDao.listUser3(rowBounds);
    for (User user : users) {
        System.out.println(user.toString());
    }
}
  • 测试,取第二页的4行数据,即第5行到第8行的数据
@Test
void test3() {
    RowBounds rowBounds = new RowBounds(4, 4);
    List<User> users = userDao.listUser3(rowBounds);
    for (User user : users) {
        System.out.println(user.toString());
    }
}

🏁以上就是对几种分页方式的简单介绍,你学"废"了么🌚,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助,那就动动你的小指头,点个赞👍吧😋😻😍

默认标题_动态分割线_2021-07-15-0.gif