MyBatis手动SQL分页
不少人在使用MyBatis时,涉及分页会使用PageHelper分页工具。在只对单表或者一对一的情况下,PageHelper确实挺简单方便的,但在一对多的多表联表查询时,却会出现某些问题,可以查看这篇文章。
相比使用PageHelper分页工具,我们可以采取更加保险的原始分页(虽然相对会麻烦点,但却是最靠谱的),而且只需进行两次数据库查询,节省开销。
关于分页,其实最关键是获取选取页的如果数据以及总记录数。
案例:
三张表的初始数据:
老师表
CREATE TABLE `teacher` (`tid` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',`tname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '老师名字',PRIMARY KEY (`tid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES (1, '张老师');
INSERT INTO `teacher` VALUES (2, '李老师');
INSERT INTO `teacher` VALUES (3, '王老师');SET FOREIGN_KEY_CHECKS = 1;
班级表
CREATE TABLE `class` (`cid` int(11) NOT NULL AUTO_INCREMENT COMMENT '班级id',`cname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '班级名称',`tid` int(11) NOT NULL COMMENT '老师id',PRIMARY KEY (`cid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of class
-- ----------------------------
INSERT INTO `class` VALUES (1, '文一班', 1);
INSERT INTO `class` VALUES (2, '文二班', 1);
INSERT INTO `class` VALUES (3, '理一班', 2);
INSERT INTO `class` VALUES (4, '理二班', 2);SET FOREIGN_KEY_CHECKS = 1;
学生表
CREATE TABLE `student` (`sid` int(11) NOT NULL COMMENT '学生id',`sname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '学生名字',`cid` int(11) NOT NULL COMMENT '班级id',PRIMARY KEY (`sid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '麦兜', 1);
INSERT INTO `student` VALUES (2, '麦唛', 1);
INSERT INTO `student` VALUES (3, '阿May', 2);
INSERT INTO `student` VALUES (4, '得巴', 3);
INSERT INTO `student` VALUES (5, '阿辉', 4);SET FOREIGN_KEY_CHECKS = 1;
三者关系:老师一对多班级,班级一对多学生
需求:根据条件查出老师以及老师所拥有的学生(注意老师是主表)
所有数据:
代码(只贴关键部分):
分页PageInfo自定义分装类(用于接收封装返回的数据,可根据自己的实际需要添加一些字段);
import java.util.List;public class PageInfo<T> {protected int pageNum = 1;//页码protected int pageSize = 10;//返回条数protected long totalRecord = -1;//总记录数protected int totalPage = -1;//总页数protected int startIndex = 0; //第几条记录开始protected List<T> resultList;//结果集public PageInfo() {}public PageInfo(int pageSize, int pageNum) {this.pageSize = pageSize;this.pageNum = pageNum;}public PageInfo(Integer pageNum) {if (pageNum != null) {this.pageNum = pageNum.intValue();}}public int getPageNum() {return pageNum;}public void setPageNum(int pageNum) {this.pageNum = pageNum;setPageSize(this.pageSize);}public int getPageSize() {return pageSize;}public void setPageSize(int pageSize) {this.pageSize = pageSize;computeTotalPage();}public long getTotalRecord() {return totalRecord;}public int getTotalPage() {return totalPage;}public void setTotalRecord(long totalRecord) {this.totalRecord = totalRecord;computeTotalPage();}public int getStartIndex() {return (pageNum - 1) * pageSize;}protected void computeTotalPage() {if (getPageSize() > 0 && getTotalRecord() > -1) {this.totalPage = (int) (getTotalRecord() % getPageSize() == 0 ? getTotalRecord()/ getPageSize(): getTotalRecord() / getPageSize() + 1);}if (this.totalPage == 0) {this.totalPage = 1;}}public List<T> getResultList() {return resultList;}public void setResultList(List<T> resultList) {this.resultList = resultList;}}
service层(封装选取页的结果数据以及总记录数):
@Service
public class TeacherService {@ResourceTeacherMapper teacherMapper;public PageInfo selectListByPageOriginal(PageParam pageParam) {// mysql的limit分页语句: limit startIndex, pageSize// 所以需要传的参数是startIndex和pageSizeList<TeacherDto> resultList = teacherMapper.selectListByPageOriginal((pageParam.getPageNum()-1)*pageParam.getPageSize(), pageParam.getPageSize());Integer totalRecord = teacherMapper.selectTtoal();PageInfo pageInfo = new PageInfo();pageInfo.setPageNum(pageParam.getPageNum());pageInfo.setPageSize(pageParam.getPageSize());pageInfo.setTotalRecord(totalRecord);pageInfo.setResultList(resultList);return pageInfo;}
}
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.example.page.dao.TeacherMapper"><resultMap id="TeacherDtoMap" type="com.example.page.dto.TeacherDto"><id column="tid" jdbcType="INTEGER" property="tid" /><result column="tname" jdbcType="VARCHAR" property="tname" /><collection property="classDtoList" resultMap="classDtoMap" javaType="java.util.List"></collection></resultMap><resultMap id="classDtoMap" type="com.example.page.dto.ClassDto"><id column="cid" jdbcType="INTEGER" property="cid" /><result column="tid" jdbcType="INTEGER" property="tid" /><result column="cname" jdbcType="VARCHAR" property="cname" /><collection property="studentDtoList" ofType="com.example.page.dto.StudentDto" javaType="java.util.List"><id column="sid" jdbcType="INTEGER" property="sid" /><result column="cid" jdbcType="INTEGER" property="cid" /><result column="sname" jdbcType="VARCHAR" property="sname" /></collection></resultMap><select id="selectListByPageOriginal" resultMap="TeacherDtoMap">SELECTt1.*, t2.cid, t2.cname, t3.sid, t3.sname FROM (SELECT * FROM teacher LIMIT #{startIndex}, #{pageSize}) t1 LEFT JOIN class t2 ON t1.tid = t2.tid LEFT JOIN student t3 ON t2.cid = t3.cid</select><select id="selectTtoal" resultType="java.lang.Integer">SELECT count(1) FROM (SELECT t1.tid FROM teacher t1 LEFT JOIN class t2 ON t1.tid = t2.tid LEFT JOIN student t3 ON t2.cid = t3.cid GROUP BY t1.tid) t4</select></mapper>
根据接口返回的结果,可看到当当前页为1,页大小为2时,会把张老师以及李老师的数据查询出来:
说明:
- 在一对多的情况下,选取页的结果数据需要在主表中进行limit(假如有加条件判断的,需自主去分辨是主表的条件还是从表的条件),不能放在最外面,错误的写法如
SELECT t1.*, t2.cid, t2.cname, t3.sid, t3.sname FROM teacher t1 LEFT JOIN class t2 ON t1.tid = t2.tid LEFT JOIN student t3 ON t2.cid = t3.cid LIMIT #{startIndex}, #{pageSize}
这样是对所有join查询得出来的结果分页
正确的sql查询语句查出的结果则是以下:
- 获取的总记录数也应该是主表的总数(只需确保主表的主键不重复就可以了,可以通过group by主键语句或者distinct去重主键),即便有加条件判断。
更多的细节希望能举一反三,这里不做详细说明了!
MyBatis手动SQL分页相关推荐
- Mybatis最入门---分页查询(逻辑分页与SQL语句分页)
[一步是咫尺,一步即天涯] 到目前为止,我们介绍的Mybatis种种查询都是一次性的查询出所有结果并返回给上层.但是,在实际开发过程中,在大量数据存在的情况下,是很少这么做的.本文,我们将从逻辑分页, ...
- Mybatis动态sql和分页
mybatis动态sql 1.1 if1.2 trim1.3 foreach1.4 其他choose/set/where 动态sql代码展示 <select id="list1&quo ...
- mybatis动态sql及分页
1. 动态sql简述 mybatis的动态sql语句是基于OGNL表达式的.可以方便的在sql语句中实现某些逻辑. 总体说来mybatis动态SQL语句主要有以下几类: if 语句 (简单的条件判断) ...
- Mybatis借助Sql语句进行分页
实现:通过sql语句实现分页 在FcTagNumberInfoMapper接口中添加sql语句查询的方法 public List<FcTagNumberInfo> selectFcTagN ...
- sql注入及mybatis防止sql注入
一.Sql 注入漏洞详解 Sql 注入产生原因及威胁: 当我们访问动态网页时, Web 服务器会向数据访问层发起 Sql 查询请求,如果权限验证通过就会执行 Sql 语句.这种网站内部直接发送的Sql ...
- springboot+mybatis实现数据分页(三种方式)
项目准备 1.创建用户表 2.使用spring初始化向导快速创建项目,勾选mybatis,web,jdbc,driver 添加lombok插件 <?xml version="1.0&q ...
- mybatis 调用存储过程_你真的该进来了解下MyBatis的SQL工作流程了
前言 MyBatis可能很多人都一直在用,但是MyBatis的SQL执行流程可能并不是所有人都清楚了,那么既然进来了,通读本文你将收获如下: 1.Mapper接口和映射文件是如何进行绑定的 2.MyB ...
- (4) hibernate增删查改+批量操作+类似Mybatis动态sql
简介 采用spring + hibernate + freemaker+ maven搭建起来的一个hibernate增删查改和 类似mybatis动态sql查询的一个案例 增删查改demo + 动态s ...
- Mybatis四种分页方式
1.数组分页 查询出全部数据,然后再list中截取需要的部分. mybatis接口 List<Student> queryStudentsByArray(); xml配置文件 <se ...
最新文章
- 高考大数据:哪个省才是高考地狱模式?结论和想象不太一样
- 1354. 等差数列【一般 / 暴力枚举】
- Hyperledger Fabric 1.0 实战开发系列 第四课 搭建node.js服务器
- 血栓清道夫机器人_血栓“清道夫”找到了!洋葱排最后,排在第一很多人并不知道...
- android动画延迟执行,Android 过渡动画框架
- DOM——创建节点及节点属性与内部插入append()和appendTo()
- 疯子的算法总结(二) STL Ⅰ 算法 ( algorithm )
- 在Spring中记录JAX-WS SOAP消息
- cepl进程 Linux,Ubuntu下NS2-2.33安装过程
- 控制台发送get命令_.NET Core使用命令行参数库构建控制台应用程序
- SSH三大框架的概述
- 上海电信中兴B860A 4K版破解
- 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java文创产品推荐系统设计与实现95ml5
- kali2020.4中文安装后,fcitx配置框中空白,无法添加输入法,请做如下操作尝试修复
- 七日杀 服务器不显示,七日杀进服务器不显示画面 | 手游网游页游攻略大全
- Parameter 'cId' not found. Available parameters are [id, param1]
- (附源码)anjule客户信息管理系统 毕业设计 181936
- [fyne] build constraints exclude all Go files in
- 项目经理start法则_开放科学项目的7条经验法则
- codeblocks||=== Build file: no target in no project (compiler: unknown) ===