一、为什么要使用分页插件
如果不使用分页插件,那需要我们在写 SQL 语句的时候手动实现分页,SQL 语句的编写如下:
select 字段名1,字段名2,... from 表名 where 查询条件 limit startIndex,pageSize
- pageSize:每页显示的条数
- pageNum:当前页的页面
- startIndex:当前页的起始索引,默认从 0 开始,index = (pageNum-1)*pageSize
- count:总记录数
- totalPage:总页数,totalPage = (count+pageSize-1)/pageSize
实际上,每次在进行分页请求发送的时候,都是要发送两个数据的:(1)pageNum(2)pageSize
二、MyBatisu环境搭建
2.1、数据的准备
CREATE DATABASE IF NOT EXISTS db_test;
USE db_test;
CREATE TABLE IF NOT EXISTS t_person(
id INT PRIMARY KEY auto_increment,
name VARCHAR(30) NOT NULL,
age INT
);
INSERT INTO t_person
VALUES(null,'Sakura',10),
(null,'Sakura',12),
(null,'Mikoto',14),
(null,'Shana',15),
(null,'Shana',16),
(null,'Akame',null),
(null,'Kurome',null),
(null,'Mine',15),
(null,'Leone',23),
(null,'Sheele',24),
(null,'Najenda',16),
(null,'Chelsea',21),
(null,'Esdese',20),
(null,'Esdeath',20),
(null,'Rimuru',null),
(null,'Shieru',null),
(null,'Izawa',null),
(null,'Shuna',null),
(null,'Shion',null),
(null,'Nanoha',9),
(null,'Nanoha',10),
(null,'Nanoha',19),
(null,'Nanoha',20),
(null,'Nanoha',23),
(null,'Nanoha',25),
(null,'Fate',9),
(null,'Fate',10),
(null,'Fate',19),
(null,'Fate',20),
(null,'Fate',23),
(null,'Fate',25);
2.2、导入jar包
通过 maven 的方式导入 jar包,打包方式设置为 jar 包即可。
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!-- junit 测试程序 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
2.3、创建核心配置文件
创建 MyBatis 的核心配置文件,习惯上命名为 mybatis-config.xml,这个文件名仅仅只是建议,并非强制要求。配置 MyBatis 的核心配置文件中的标签必须按照固定的顺序:
properties --> settings --> typeAliases --> typeHandlers --> objectFactory --> objectWrapperFactory --> reflectorFactory --> plugins --> environments --> databaseIdProvider --> mappers
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引入数据库连接信息的配置文件 -->
<properties resource="jdbc.properties"/>
<!-- settings标签的内容是MyBatis极为重要的调整设置,它们会改变MyBatis的运行时行为 -->
<settings>
<!-- 指定MyBatis所有日志的具体实现,未指定时将自动查找 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启驼峰命名自动映射 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<!-- 将这个包下的所有的类全部起别名,别名就是类简名,不区分大小写 -->
<package name="star.light.pojo"/>
</typeAliases>
<!-- environments:配置多个连接数据库环境 -->
<environments default="development">
<!-- environment:配置某个具体的环境 -->
<environment id="development">
<!-- 设置事务管理方式 -->
<transactionManager type="JDBC"/>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<!-- 设置连接数据库的驱动 -->
<property name="driver" value="${jdbc.driver}"/>
<!-- 设置连接数据库的地址 -->
<property name="url" value="${jdbc.url}"/>
<!-- 设置连接数据库的用户名 -->
<property name="username" value="${jdbc.username}"/>
<!-- 设置连接数据库的密码 -->
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<!-- 从Mapper接口所在的包的路径中加载 -->
<package name="star.light.mapper"/>
</mappers>
</configuration>
数据库连接信息的配置文件:jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_test
jdbc.username=root
jdbc.password=abc123
2.4、创建MyBatis的映射文件
映射文件的命名应该为 表所对应的实体类的类名+Mapper.xml。一个映射文件对应一个实体类,对应一张表的操作。MyBatis映射文件用于编写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">
<!--
namespace用来指定命名空间的,防止id重复
如果在多个Mapper文件中,SQL语句的id重复,这时可以在Java程序中写namespace.id
实质上,本质上,MyBatis中的SQLId的完整写法为namespace.id
-->
<mapper namespace="star.light.mapper.PersonMapper">
<!-- List<Person> getAllPerson(); -->
<select id="getAllPerson" resultType="Person">
select id, name, age from t_person
</select>
</mapper>
2.5、创建mapper接口
MyBatis 中的 mapper 接口相当于以前的 dao。但是区别在于,mapper 仅仅是接口,我们不需要提供实现类。
package star.light.mapper;
import star.light.pojo.Person;
import java.util.List;
public interface PersonMapper {
/**
* MyBatis 面向接口编程的两个一致:
* 1、映射文件的 namespace 要和 mapper 接口的全类名保持一致
* 2、映射文件中 SQL 语句的 id 要和 mapper 接口中方法名一致
*/
List<Person> getAllPerson();
}
2.6、创建实体类
package star.light.pojo;
public class Person {
private Integer id;
private String name;
private Integer age;
public Person() {
}
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.7、封装SqlSessionUtil工具类
package star.light.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
public class SqlSessionUtil {
private static SqlSessionFactory sqlSessionFactory;
// 为了防止new对象,工具类的构造方法一般都是私有的
// 工具类中所有的方法都是静态的,直接采用类型即可调用,不需要new对象
private SqlSessionUtil(){}
// 静态代码块在类加载的时候执行
// SqlSesionUtil工具类在进行第一次加载的时候,解析MyBatis和核心配置文件,创建SqlSessionFactory对象
static {
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 获取会话对象
* @return 会话对象
*/
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
三、配置分页插件
①添加依赖和插件:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
②配置分页插件:
在MyBatis的核心配置文件中配置插件。
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
四、分页插件的使用
测试程序:
package star.light.test;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import star.light.mapper.PersonMapper;
import star.light.pojo.Person;
import star.light.util.SqlSessionUtil;
import java.util.List;
public class PageTest {
@Test
public void testSelectAllPerson(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
// 在执行DQL语句之前,开启分页功能
int pageNum = 2;
int pageSize = 5;
PageHelper.startPage(pageNum,pageSize);
List<Person> persons = mapper.getAllPerson();
// persons.forEach(System.out::println);
// 封装分页信息对象
PageInfo<Person> personPageInfo = new PageInfo<>(persons, 5);
System.out.println(personPageInfo);
sqlSession.close();
}
}
-
在查询功能之前使用PageHelper.startPage(int pageNum, int pageSize)开启分页功能
- pageNum:当前页的页码
- pageSize:每页显示的条数
-
在查询获取list集合之后,使用PageInfo
<T>
pageInfo = new PageInfo<>(List<T>
list, int navigatePages)获取分页相关数据- list:分页之后的数据
- navigatePages:导航分页的页码数
分页相关数据:
PageInfo{
pageNum=2, pageSize=5, size=5,
startRow=6, endRow=10,
total=31, pages=7,
list=Page{
count=true,
pageNum=2, pageSize=5,
startRow=5, endRow=10,
total=31, pages=7,
reasonable=false,
pageSizeZero=false
}
[Person{id=6, name='Akame', age=null},
Person{id=7, name='Kurome', age=null},
Person{id=8, name='Mine', age=15},
Person{id=9, name='Leone', age=23},
Person{id=10, name='Sheele', age=24}],
prePage=1, nextPage=3,
isFirstPage=false, isLastPage=false,
hasPreviousPage=true, hasNextPage=true,
navigatePages=5,
navigateFirstPage=1, navigateLastPage=5,
navigatepageNums=[1, 2, 3, 4, 5]
}
- pageNum:当前页的页码
- pageSize:每页显示的条数
- size:当前页显示的真实条数
- total:总记录数
- pages:总页数
- prePage:上一页的页码
- nextPage:下一页的页码
- isFirstPage/isLastPage:是否为第一页/最后一页
- hasPreviousPage/hasNextPage:是否存在上一页/下一页
- navigatePages:导航分页的页码数
- navigatepageNums:导航分页的页码,[1,2,3,4,5]