1.分页概念
用户查询的数据不可能一次性全部展示给用户(如果用户有一万条数据呢),而是分页展示给用户,这就是分页查询。
2.原生写法
步骤:
controller层:
- 接受请求,请求数据=页码+每页数量+查询条件(非必须)
- 调用业务层完成分页查询
- 将结果响应给前端
service层:
- 换算起始查询的行号(就是用户点击的第几页,该页的第一条是数据的第几行)
- 调用数据层完成分页查询
- 调用数据层完成数量的查询
- 封装结果(数据+数量)【创建一个对象接受】
- 返回给controller层
mapper层:
- 动态SQL拼接带条件的分页查询数据(数据)
- 动态查询符合条件的数据总数(数量)
为啥要封装一个对象接受呢?
客户端需要两条数据,一个是分页查询的数据,还有一个是分页查询的总条数,但是返回值只能返回一个,因此要封装在一个对象中,代码如下。
package com.its.domain; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @Data @AllArgsConstructor @NoArgsConstructor public class PageResult { private Object data; private Long total; }
案例测试
需求:将所有的房间分页查询出来展示。
controller层方法
package com.its.controller;
import com.its.domain.PageResult;
import com.its.domain.Result;
import com.its.domain.Room;
import com.its.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@PostMapping("/selectAllRoom")
public Result selectAllRoom(Room room, Integer pageNo, Integer pageSize){
// 1.接受请求,请求数据为 页码数+每页的数量+查询的条件
return testService.selectAllRoom(room,pageNo,pageSize);
}
}
service层代码
package com.its.service.Impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.its.domain.PageResult;
import com.its.domain.Result;
import com.its.domain.Room;
import com.its.mapper.TestMapper;
import com.its.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Override
public Result selectAllRoom(Room room, Integer pageNo, Integer pageSize) {
// 将页码数换算成行数
int pageStart = (pageNo-1)*pageSize;
// 调用mapper层完成分页查询
List<Room> rooms = testMapper.selectAllRoom(room, pageStart, pageSize);
// 再查询总数量
long total = testMapper.selectTotal(room);
// 封装成对象返回
Result result = new Result(rooms, total);
return result;
}
}
mapper
package com.its.mapper;
import com.its.domain.PageResult;
import com.its.domain.Room;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface TestMapper {
// 原生分页查询
List<Room> selectAllRoom(@Param("room") Room room,
@Param("pageStart") Integer pageStart,
@Param("pageSize") Integer pageSize);
int selectTotal(@Param("room") Room room);
}
xml映射SQL文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.its.mapper.TestMapper">
//分页查询符合条件的数据
<select id="selectAllRoom" resultType="com.its.domain.Room">
select * from room
<where>
<if test="room.info!=null and room.info!=''">
info like concat('%',#{room.info},'%')
</if>
</where>
limit #{pageStart},#{pageSize}
</select>
//查询总数量
<select id="selectTotal" resultType="java.lang.Integer">
select count(1) from room
<where>
<if test="room.info!=null and room.info!=''">
info like concat('%',#{room.info},'%')
</if>
</where>
</select>
</mapper>
在postMan中测试得到如下结果,分页查询完成
3.PageHelper插件分页查询
3.1 介绍
步骤:
controller层(不变):
- 接受请求,请求数据=页码+每页数量+查询条件(非必须)
- 调用业务层完成分页查询
- 将结果响应给前端
service层:
- 调用PageHelper中的 startPage(参数页码,每页数量) 方法,然后返回一个Page对象。
- 调用数据层完成分页查询
- 直接用Page对象中的方法封装结果(数据+数量)
- 返回给controller层
mapper层:
- 直接动态SQL拼接带查询条件的查询(SQL语句中不用使用limit)
【原理介绍】
流程其实是一样的,只是该插件在内部封装了一些方法供我们使用。PageHelper插件基于拦截的原理实现对mapper层编写的SQL语句进行二次处理,如下:
- 会给查询的SQL语句进行语句拼接,添加limit,并赋值分页条件
- 会动态生成查询数量的SQL语句并执行。
- 会将分页相关的所有结果(分页数量+数量+页码数+起始查询行号+每页的数量等)封装到一个Page对象中。
Page中方法介绍:
3.2 使用
代码书写,还是以上面为例。
(1)导入PageHelper所需依赖
<!--分页插件依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version>
</dependency>
(2)controller层
package com.its.controller;
import com.its.domain.PageResult;
import com.its.domain.Result;
import com.its.domain.Room;
import com.its.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
TestService testService;
@PostMapping("/selectAll")
//参数为查询条件,页数,每页的展示数
public PageResult selectAll(Room room,Integer pageNo,Integer pageSize){
PageResult pageResult = testService.selectAll(room, pageNo, pageSize);
return pageResult;
}
}
(3)service层
package com.its.service.Impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.its.domain.PageResult;
import com.its.domain.Result;
import com.its.domain.Room;
import com.its.mapper.TestMapper;
import com.its.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
TestMapper testMapper;
@Override
public PageResult selectAll(Room room, Integer pageNo, Integer pageSize) {
// 开启分页查询,当执行查询时,插件进行相关的sql拦截进行分页操作,返回一个page对象
Page<Room> page = PageHelper.startPage(pageNo, pageSize);
// 调用mapper层完成查询
testMapper.selectAll(room);
// 封装结果
PageResult pageResult = new PageResult(page.getResult(), page.getEndRow());
System.out.println(pageResult);
System.out.println(page);
return pageResult;
}
}
(4)mapper层
package com.its.mapper;
import com.its.domain.PageResult;
import com.its.domain.Room;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface TestMapper {
// 使用分页插件分页查询
List<Room> selectAll(@Param("room") Room room);
}
(5)xml映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.its.mapper.TestMapper">
<select id="selectAll" resultType="com.its.domain.Room">
select * from room
</select>
</mapper>
(6)测试结果:
3.3 Page对象和PageInf对象
在 PageHelper 中,Page 和 PageInfo 都是用来处理分页数据的重要类。
Page对象
- Page 是一个接口,它包含分页数据以及一些基本的分页信息(如总记录数、当前页等)。当使用 PageHelper 进行分页查询时,查询结果会被自动封装到一个实现了 Page 接口的对象中。
PageInfo对象
- PageInfo 是 PageHelper 提供的一个类,用于封装更详细的分页信息。它不仅包含了分页数据,还提供了更多的辅助信息,如是否为第一页、最后一页、导航页码等。
使用PageInfo进行上面的替换,业务层代码为
版权归原作者 空谷忧人 所有, 如有侵权,请联系我们删除。