基于Mybatis,MybatisPlus实现数据库查询分页功能
目录
- 基于Mybatis,MybatisPlus实现数据库查询分页功能
- 使用Mybatis插件实现分页
- 数据库准备
- 分页插件配置和使用
- 常用数据:
- 使用MybatisPlus插件实现分页
- 数据库准备
- 分页插件配置和使用
- 自定义分页查询
- 总结
在实际项目开发过程中,分页查询功能用的还是比较多的,自己也写过不少,但每次写也都要翻一些资料,故自行整理一篇以备查看
使用Mybatis插件实现分页
使用pagehelper插件实现分页功能
数据库准备
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_emp
-- ----------------------------
DROP TABLE IF EXISTS `t_emp`;
CREATE TABLE `t_emp` (
`eid` int(11) NOT NULL AUTO_INCREMENT,
`emp_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`age` int(11) NULL DEFAULT NULL,
`sex` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`email` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`did` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`eid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 53 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_emp
-- ----------------------------
INSERT INTO `t_emp` VALUES (1, '张三', 23, '男', '123@qq.com', 1);
INSERT INTO `t_emp` VALUES (2, '李四', 43, '女', '123@qq.com', 2);
INSERT INTO `t_emp` VALUES (3, '王五', 12, '女', '123@qq.com', 3);
INSERT INTO `t_emp` VALUES (4, '赵六', 54, '男', '123@qq.com', 1);
INSERT INTO `t_emp` VALUES (5, '田七', 23, '男', '123@qq.com', 2);
INSERT INTO `t_emp` VALUES (11, 'a', NULL, NULL, NULL, NULL);
INSERT INTO `t_emp` VALUES (12, 'a', NULL, NULL, NULL, NULL);
INSERT INTO `t_emp` VALUES (13, 'a1', 23, '男', '123@qq.com', NULL);
INSERT INTO `t_emp` VALUES (14, 'a2', 23, '男', '123@qq.com', NULL);
INSERT INTO `t_emp` VALUES (15, 'a3', 23, '男', '123@qq.com', NULL);
INSERT INTO `t_emp` VALUES (16, 'a1', 23, '男', '123@qq.com', NULL);
INSERT INTO `t_emp` VALUES (17, 'a2', 23, '男', '123@qq.com', NULL);
INSERT INTO `t_emp` VALUES (18, 'a3', 23, '男', '123@qq.com', NULL);
INSERT INTO `t_emp` VALUES (19, 'a1', 23, '男', '123@qq.com', NULL);
INSERT INTO `t_emp` VALUES (20, 'a2', 23, '男', '123@qq.com', NULL);
INSERT INTO `t_emp` VALUES (21, 'a3', 23, '男', '123@qq.com', NULL);
INSERT INTO `t_emp` VALUES (22, 'a', NULL, NULL, NULL, NULL);
INSERT INTO `t_emp` VALUES (23, 'a', NULL, NULL, NULL, NULL);
INSERT INTO `t_emp` VALUES (24, 'a', NULL, NULL, NULL, NULL);
SET FOREIGN_KEY_CHECKS = 1;
分页插件配置和使用
1、添加pom依赖
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
2、在MyBatis的核心配置文件(mybatis-config.xml)中配置插件
该插件就是一种拦截器,给查询添加Limit
限制
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<!--设置连接数据库的环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<property name="driver" value="${jdbc.driver}"/>
<!-- <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>-->
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
3、创建测试方法测试功能
@Test
public void testPage() {
SqlSession sqlSession = null;
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
// pageNum=5, pageSize=4, 表示第五页,每页四条数据
PageHelper.startPage(5, 4);
List<Emp> list = mapper.selectAll();
PageInfo<Emp> page = new PageInfo<>(list,5);
list.forEach(emp -> System.out.println(emp));
System.out.println(page);
} catch (IOException e) {
e.printStackTrace();
}
}
4、结果
PageInfo{pageNum=5, pageSize=4, size=4, startRow=17, endRow=20, total=47, pages=12, list=Page{count=true, pageNum=5, pageSize=4, startRow=16, endRow=20, total=47, pages=12, reasonable=false, pageSizeZero=false}[Emp{eid=22, empName='a', age=null, sex='null', email='null', did=null}, Emp{eid=23, empName='a', age=null, sex='null', email='null', did=null}, Emp{eid=24, empName='a', age=null, sex='null', email='null', did=null}, Emp{eid=25, empName='a', age=null, sex='null', email='null', did=null}], prePage=4, nextPage=6, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, navigatePages=5, navigateFirstPage=3, navigateLastPage=7, navigatepageNums=[3, 4, 5, 6, 7]}
常用数据:
- pageNum:当前页的页码
- pageSize:每页显示的条数
- size:当前页显示的真实条数
- total:总记录数
- pages:总页数
- prePage:上一页的页码
- nextPage:下一页的页码
- isFirstPage/isLastPage:是否为第一页/最后一页
- hasPreviousPage/hasNextPage:是否存在上一页/下一页
- navigatePages:导航分页的页码数
- navigatepageNums:导航分页的页码,[1,2,3,4,5]
使用MybatisPlus插件实现分页
可见,上述Mybatis基于xml配置的方式实现分页,还是有些麻烦的。MybatisPlus是对Mybatis的进一步封装和加强,因此分页功能会比Mybatis更便捷。测试的SpringBoot目录结构如下
数据库准备
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名',
`age` int(11) NULL DEFAULT NULL COMMENT '年龄',
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'Jone', 18, 'test1@baomidou.com');
INSERT INTO `user` VALUES (2, 'Jack', 20, 'test2@baomidou.com');
INSERT INTO `user` VALUES (3, 'Tom', 28, 'test3@baomidou.com');
INSERT INTO `user` VALUES (4, 'Sandy', 21, 'test4@baomidou.com');
INSERT INTO `user` VALUES (5, 'Billie', 24, 'test5@baomidou.com');
SET FOREIGN_KEY_CHECKS = 1;
分页插件配置和使用
1、配置分页插件
@Configuration
// 扫描mapper接口所在的包
@MapperScan("com.mystudy.mybatisplus.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
// 分页插件配置
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor;
}
}
2、创建mapper文件
@Repository
public interface UserMapper extends BaseMapper<User> {
}
这里什么也不需要写,继承BaseMapper
类即可,MybatisPlus提供了默认方法
3、创建测试方法测试功能
@SpringBootTest
public class PluginsTest {
@Autowired
private UserMapper userMapper;
@Test
public void testPage(){
// 设置当前页和每页显示的条数,即第一页,每页三个,因此会将前三条记录查出
Page<User> page = new Page<>(1, 3);
userMapper.selectPage(page, null);
System.out.println("===============================");
System.out.println(page.getRecords());
System.out.println(page.getTotal());
System.out.println(page.getPages());
System.out.println(page.hasNext());
System.out.println(page.hasPrevious());
}
}
4、查询结果
[User(id=1, name=Jone, age=18, email=test1@baomidou.com), User(id=2, name=Jack, age=20, email=test2@baomidou.com), User(id=3, name=Tom, age=28, email=test3@baomidou.com)]
5
2
true
false
自定义分页查询
1、自定义查询条件
自定义分页功能,通过年龄查询用户信息并分页
@Repository
public interface UserMapper extends BaseMapper<User> {
/**
* 自定义分页功能,通过年龄查询用户信息并分页
* @param page MybatisPlus提供的分页对象,必须位于第一个参数的位置
* @param age
* @return
*/
Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);
}
2、创建xml映射文件(与Mybatis方式相同)
<?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.mystudy.mybatisplus.mapper.UserMapper">
<!-- Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);-->
<select id="selectPageVo" resultType="User">
select id, name, age, email from user where age > #{age}
</select>
</mapper>
这里可以对User进行别名配置,在yml配置文件中:
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 配置类型别名所对应的包
type-aliases-package: com.mystudy.mybatisplus.pojo
可以看到,我们并没有在sql语句中写关于分页的信息
3、创建测试方法测试功能
@Test
public void testPageVo(){
Page<User> page = new Page<>(1, 3);
userMapper.selectPageVo(page, 20);
System.out.println("===============================");
System.out.println(page.getRecords());
System.out.println(page.getTotal());
System.out.println(page.getPages());
System.out.println(page.hasNext());
System.out.println(page.hasPrevious());
}
4、查询结果
[User(id=3, name=Tom, age=28, email=test3@baomidou.com), User(id=4, name=Sandy, age=21, email=test4@baomidou.com), User(id=5, name=Billie, age=24, email=test5@baomidou.com)]
3
1
false
false
总结
在真正项目开发中,分页功能是必不可少的,需要前端向后端传输page和pageSize两个参数,我们这里的功能仅作演示,因此是写死的。熟能生巧,多用多会。