Mybatis高级查询(三)
分页查询
问题:一次性查询10条数据如何实现?
sql:select * from tableName limit 10;
问题:查询第6条到第10条的数据怎么实现呢
sql:select * from tableName limit 5,10(注意首个是从0开始的)
如果一页的数据很少,这当然用不上分页,那如果数据成千上万都在一页加载的话会极大的拖慢运行速度和机器资源,导致大量的时间和资源都用在了查询上,这种情况就需要使用到分页,设定一页有多少数据,就只加载这一些数据,大大的提高了程序执行效率
pageHelper
从底层原理来讲手动分页也是可以实现的,但是如果数据非常多那么实现起来就不太方便,如果使用pageHelper插件来实现就会方便很多
新建一个Maven项目
添加依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<!-- 阿里巴巴连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<!-- 日志框架-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
<!-- Servlet支持Request和Response-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!-- 整合对jsp的支持-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
</dependency>
<!-- 阿里巴巴json转换工具 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.6</version>
</dependency>
dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.0.6</version>
</dependency>
</dependencies>
添加数据库表对应的pojo类user,并提供set/get方法
public class User {
private Integer id;
private String username;
private String sex;
private String address;
private Date birthday;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
在sqlMapConfig.xml配置的标签下添加分页插件配置
<!-- 分页插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<!--设置为true时,如果pageSize=0就会查询出全部的结果-->
<property name="pageSizeZero" value="true"/>
</plugin>
</plugins>
.在OrdersMapper接口中添加查询用户信息方法
//分页查询方法
public List<User> queryUser();
添加AutoController类
@Controller
public class AutoController {
/**
* 分页查询
* @return
*/
@RequestMapping("/pagetest")
//@RequestParam注解如果传入的page没有值那就使用默认值1
public String queryUser(@RequestParam(required = true,defaultValue = "1") Integer page, Model model) throws IOException {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
OrdersMapper mapper = session.getMapper(OrdersMapper.class);
//开始执行分页,每页两条数据
PageHelper.startPage(page,2);
List<User> users = mapper.queryUser();
//创建pageInfo对象保存查询出的结果
PageInfo<User> pageInfo = new PageInfo<>(users);
//将数据存入model中
model.addAttribute("users",users);
model.addAttribute("page",pageInfo);
return "show";
}
}
show.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户信息</title>
</head>
<body>
<div align="center">
<h1>用户信息</h1>
<table border="1" cellspacing="0">
<tr>
<td>用户编号</td>
<td>用户名称</td>
<td>性别</td>
<td>生日</td>
<td>地址</td>
</tr>
<c:forEach items="${users}" var="user">
<tr>
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.sex}</td>
<td>${user.birthday}</td>
<td>${user.address}</td>
</tr>
</c:forEach>
</table>
<p>一共${page.pages}页</p>
<p>第${page.pageNum}页</p>
<a href="pagetest?page=${page.firstPage}">第一页</a>
<a href="pagetest?page=${page.prePage}">上一页</a>
<a href="pagetest?page=${page.nextPage}">下一页</a>
<a href="pagetest?page=${page.lastPage}">最后一页</a>
</div>
</body>
</html>
PageInfo对象的常用方法
方法 | 作用 |
---|---|
PageInfo.list | 结果集 |
PageInfo.pageNum | 当前页码 |
PageInfo.pageSize | 当前页面显示的数据条目 |
PageInfo.pages | 总页数 |
PageInfo.total | 数据的总条目数 |
PageInfo.prePage | 上一页 |
PageInfo.nextPage | 下一页 |
PageInfo.isFirstPage | 是否为第一页 |
PageInfo.isLastPage | 是否为最后一页 |
PageInfo.hasPreviousPage | 是否有上一页 |
PageHelper.hasNextPage | 是否有下一页 |
浅析pagehelper分页原理:
Mybatis SqlSessionFactory —> SqlSession —> Executor —> MappedStatement
***在Executor和MappedStatement之间***MyBatis的plugin实现了Interceptor接口,可以在插件中获得要执行的sql语句。在sql语句中添加limit语句。可以实现分页的处理
在执行MappedStatement之前PageHelper会动态的修改Sql语句,在sql语句中添加limit语句,以实现分页效果,类似于增强AOP;
把sql语句:select * from user拦截到,进行了修改变成如下语句:
select * from user limit ?,?
最后带入参数,执行查询;
select * from user limit 4,2