分页查询
分页查询将数据库中庞大的数据分段显示,每页显示用户自定义的行数,提高用户体验度,最主要的是如果一次性从服务器磁盘中读出全部数据到内存,有内存溢出的风险
真假分页
假分页: 其原理还是将所有的数据读到内存中,翻页从内存中读取数据, 优点: 实现简单,性能高 缺点:如果数据大容易造成内存溢出
真分页: 每次翻页从数据库查询数据(即磁盘) , 优点 : 不容易造成内存溢出 缺点: 实现复杂,性能相对低一些
分页效果
一般分页的功能包括: 首页 上一页 下一页 末页 当前是多少页 总共多少页 一共多少行数据 跳转到第几页 每页多少条数据 我们需要将这个数据查询出来封装到一个对象中,体现了封装思想,也节省了很多复杂代码

分页需要传递的参数
需要用户传入的参数:
currentPage: 当前页,跳转到第几页, 第一次访问,我们创建一个对象,默认值是1
pageSize: 每页显示多少行数据, 第一次我们也给个默认值 比如10条
分页需要展示的数据
1.当前页的货品信息
2.首页是第几页
3.上一页是第几页
4.下一页是第几页
5.一共有多少页,和末页的值是一样的
6.数据一共有多少条(行)
7.当前是第几页
8.每页显示多少条信息
分页需要展示的数据的来源
来源于用户上传: 当前页 , 每页显示多少条数据
来源于数据库查询 : 数据总条数 , 每一页需要展示的商品信息
来源于根据上面的已知信息计算 : 总页数 , 上一页 , 下一页
书写从数据库查询的sql语句
第一条sql 查询数据库中有多少条数据,COUNT后面不能有空格
SELECT COUNT(*) FROM 表名
第二条sql 根据传入的参数查询第几页,一页多少条数据的结果集
# 第一个 ?:从哪一个索引的数据开始查询(默认从 0 开始) # 第二个 ?:查询多少条数据 SELECT * FROM 表名 LIMIT ?, ?
接下来分析第二条 SQL 中两个 ? 取值来源:
假设 product 表中有 21 条数据,每页分 5 条数据:
查询第一页数据:SELECT * FROM product LIMIT 0, 5
查询第二页数据:SELECT * FROM product LIMIT 5, 5
查询第三页数据:SELECT * FROM product LIMIT 10, 5
查询第四页数据:SELECT * FROM product LIMIT 15, 5
通过寻找规律发现:第一个 ? 取值来源于 (currentPage - 1) * pageSize;第二个 ? 取值来源于
pageSize,即都来源于用户传递的分页参数。
总页数,上一页和下一页
// 优先计算总页数
int totalPage = rows % pageSize == 0 ? rows / pageSize : rows / pageSize + 1;
//上一页等于当前页-1,但不能超过1页界限
int prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;
//下一页等于当前页+1,但不能超过总页数界限
int nextPage = currentPage + 1 <p><strong>分页查询实现</strong></p><p>访问流程:</p><p><img src="https://img.php.cn/upload/article/000/000/164/168371161710508.png?x-oss-process=image/resize,p_40" alt="怎么用Java实现分页查询功能"></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2494" title="Java Linux版"><img
src="https://img.php.cn/upload/manual/001/221/864/6a6091217fc2f681.png" alt="Java Linux版" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2494" title="Java Linux版" class="overflowclass">Java Linux版</a>
<p class="overflowclass">Java Linux版下载入口,提供 Oracle JDK 26.0.2 官方 Linux 安装包、Java 环境配置、JDBC 数据库连接和 Java 服务端开发相关信息。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2494" title="Java Linux版" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><p><strong>封装需要展示的数据</strong></p><p>如果不封装数据,每个数据都需要存到作用域中,数据太分散,不方便统一管理</p><pre class="brush:java;">/**
* 封装结果数据(某一页的数据)
*/
@Getter
public class PageResult<t> {
// 两个用户的输入
private int currentPage; // 当前页码
private int pageSize; // 每页显示的条数
// 两条 SQL 语句执行的结果
private int totalCount; // 总条数
private List<t> data; // 当前页结果集数据
// 三个程序计算的数据
private int prevPage; // 上一页页码
private int nextPage; // 下一页页码
private int totalPage; // 总页数/末页页码
// 分页数据通过下面构造期封装好
public PageResult(int currentPage, int pageSize, int totalCount, List<t>
data) {
this.currentPage = currentPage;
this.pageSize = pageSize;
this.totalCount = totalCount;
this.data = data;
// 计算三个数据
this.totalPage = totalCount % pageSize == 0 ? totalCount / pageSize :
totalCount / pageSize + 1;
this.prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;
this.nextPage = currentPage + 1 <p><strong>持久层DAO</strong></p>
<p>Mybatis提供的操作方法只能传入一个参数执行SQL任务,而我们现在查询某一页的数据,需要知道是第几页和每页多少条数据这两个参数,所以我们需要将这两个参数封装在一个对象里面<br>编写一个类(起名叫查询对象类)来封装这些查询数据</p>
<pre class="brush:java;">@Setter
@Getter
/**
* 封装分页查询需要的两个请求传入的分页参数
*/
public class QueryObject {
private int currentPage = 1; // 当前页码,要跳转到哪一页的页码(需要给默认值)
private int pageSize = 3; // 每页显示条数(需要给默认值)
}
再书写持久层DAO接口和实现类
//DAO接口提供两个根据查询对象的查询方法
int queryForCount();
List<product> queryForList(QueryObject qo);
//DAO实现类
@Override
//查询数据库总数据条数
public int queryForCount() {
SqlSession session = MyBatisUtil.getSession();
int totalCount =
session.selectOne("cn.xxx.mapper.ProductMapper.queryForCount");
session.close();
return totalCount;
}
@Override
//查询某一页的结果集
public List<product> queryForList(QueryObject qo) {
SqlSession session = MyBatisUtil.getSession();
List<product> products =
session.selectList("cn.xxx.mapper.ProductMapper.queryForList",qo);
session.close();
return products;
}</product></product></product>
修改productMapper.xml
<select>
SELECT COUNT(*) FROM product
</select><select>
SELECT * FROM product LIMIT #{start}, #{pageSize}
</select>
修改QueryObject.java
给这个类增加getStart方法,返回根据当前页,每页大小需要从数据库从第几行开始显示
@Setter
@Getter
/**
* 封装分页查询需要的两个请求传入的分页参数
*/
public class QueryObject {
private int currentPage = 1; // 当前页码,要跳转到哪一页的页码(需要给默认值)
private int pageSize = 3; // 每页显示条数(需要给默认值)
// 用于 Limit 子句第一个 ? 取值
public int getStart(){
return (currentPage - 1) * pageSize;
}
}
业务层ProductService
调用持久层DAO完成数据的查询,并将多个数据封装到一个对象中
//IProductService接口
public interface IProductService {
/**
* 完成查询某一页的业务逻辑功能
*/
PageResult<product> query(QueryObject qo);
}
//Service实现类
public class ProductServiceImpl implements IProductService {
private IProductDAO productDAO = new ProductDAOImpl();
@Override
public PageResult<product> query(QueryObject qo) {
// 调用 DAO 查询数据数量
int totalCount = productDAO.queryForCount();
// 为了性能加入判断,若查询的数据数量为 0,说明没有数据,返回返回空集合,即集合中没有
元素
if(totalCount == 0){
return new PageResult(qo.getCurrentPage(), qo.getPageSize(),
totalCount, Collections.emptyList());
}
// 执行到这里代表有数据,查询当前页的结果数据
List<product> products = productDAO.queryForList(qo);
return new PageResult(qo.getCurrentPage(), qo.getPageSize(), totalCount,
products);
}
}</product></product></product>
前台分页功能实现
1.必须先完成业务层组件,保证后台测试通过。
2.遵循 MVC 思想。
3.浏览器发出分页请求参数(去往第几页/每页多少条数据),在 Servlet 中接收这些参数,并封装
4.到 QueryObject 对象,调用 Service 中分页查询方法(query)。
5.把得到的分页查询结果对象(PageResult)共享在请求作用域中,跳转到 JSP,显示即可。
6.修改 JSP 页面,编写出分页条信息(分页条中的信息来源于 PageResult 对象)。
修改ProductServlet.java和展示jsp
1.获取页面请求参数,判断是查询操作,调用查询方法,获取分页参数
2.将参数封装成查询对象QueryObject
3.调用业务层方法查询某一页数据
4.将查询出来的结果存到作用域中
5.转发到展示页面jsp
6.在jsp从作用域中将结果取出来响应到浏览器
//创建业务层对象
private IProductService productService = new ProductServiceImpl();
protected void list(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException {
QueryObject qo = new QueryObject();
// 获取请求参数 currentPage,并转型封装
String currentPage = req.getParameter("currentPage");
if(StringUtil.hasLength(currentPage)) {
qo.setCurrentPage(Integer.valueOf(currentPage));
}
// 获取请求参数 pageSize,并转型封装
String pageSize = req.getParameter("pageSize");
if(StringUtil.hasLength(pageSize)) {
qo.setPageSize(Integer.valueOf(pageSize));
}
// 调用业务层方法来处理请求查询某一页数据
PageResult<product> pageResult = productService.query(qo);
// 把数据共享给 list.jsp
req.setAttribute("pageResult", pageResult);
// 控制跳转到 list.jsp 页面
req.getRequestDispatcher("/WEB-INF/views/product/list.jsp").forward(req,
resp);
}</product>
修改jsp文件,使用JSTL+EL获取作用域中的数据
<title>产品列表</title>
<script>
window.onload = function () {
var trClzs = document.getElementsByClassName("trClassName");
for(var i = 0; i < trClzs.length; i++){
trClzs[i].onmouseover = function () {
console.log(1);
this.style.backgroundColor = "gray";
}
trClzs[i].onmouseout = function () {
console.log(2);
this.style.backgroundColor = "";
}
}
}
// 分页 JS
function changePageSize() {
document.forms[0].submit();
}
</script>
<a>@@##@@</a><br>
<a>添加</a>
常见问题
若开始翻页操作成功,翻了几页不能翻了,只能重启tomcat才能翻,问题: DAO中没有关闭SqlSession对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










