初步分页(MySQL)

一.MySQL分页基础

1.1.SQL语句

  1. 分页MySQL语句是:SELECT * FROM student LIMIT 0,10;
  2. 是从0开始
  3. 解释: LIMIT 第几个数据,要查多少条数据
  4. 即从第0条开始,到第9条数据

1.2.逻辑

  1. 要实现分页,必须知道某一页的数据从哪里开始,到哪里结束
  2. 规定:页面大小:每页显示的数据量。(假设每页显示10条数据)
  3. 从第0页开始计数
  4. 第n页的数据: 第(n-1) * 10+1条 – 第n * 10条
第几页 开始数据行 结束数据行
0 0 9
1 10 19
2 20 29
n n*10 (n+1)*10-1
  1. MYSQL实现分页的sql:
    limit 开始,多少条
    第0页
    select * from student limit 0,10 ;
    第1页
    select * from student limit 10,10 ;
    第2页
    select * from student limit 20,10 ;
    第n页
    select * from student limit n*10,10

mysql的分页语句:
select * from student limit 页数*页面大小,页面大小

1.4.oracle,sqlserver分页(引用)

b.oracle分页:

sqlserver/oracle:1开始计数
第n页		开始		结束
1		1		10
2		11		20
3		21		30
n		(n-1)*10+1	n*10

select *from student  where sno >=(n-1)*10+1 and sno <=n*10 ;  --此种写法的前提:必须是Id连续 ,否则 无法满足每页显示10条数据


select rownum,t.*from student t where rownum >=(n-1)*10+1 and rownum <=n*10  order by sno;
--1.如果根据sno排序则rownum会混乱(解决方案:分开使用->先只排序,再只查询rownum) 2.rownum不能查询>的数据 

select s.* from student s order by sno asc;


select rownum, t.* from
(select s.* from student s order by sno asc) t 
where rownum >=(n-1)*10+1 and rownum <=n*10 ; ;


//ORACLE\sqlserver都是从1开始计数:  (n-1)*10+1    ---  n*10 
oracle的分页查询语句:
select *from 
(
	select rownum r, t.* from
	(select s.* from student s order by sno asc) t 		10000
)
where r>=(n-1)*10+1 and <=n*10  ;				10

优化:

select *from 
(
	select rownum r, t.* from
	(select s.* from student s order by sno asc) t 		
	where rownum<=n*10 
)
where r>=(n-1)*10+1  ;	

select *from 
(
	select rownum r, t.* from
	(select s.* from student s order by sno asc) t 		
	where  rownum<=页数*页面大小 
)
where r>=(页数-1)*页面大小+1  ;	


SQLServer分页:  3种分页sql
row_number()	over(字段) ;

sqlserver2003:top  --此种分页SQL存在弊端(如果id值不连续,则不能保证每页数据量相等)
select top 页面大小 * from student where id not in 
( select top (页数-1)*页面大小 id from student  order by sno asc )



sqlserver2005之后支持:
select *from 
(
	select row_number()  over (sno order by sno asc) as r,* from student
			
	 where r<=n*10 
)
where r>=(n-1)*10+1 and  ;	

SQLServer此种分页sql与oralce分页sql的区别: 1.rownum  ,row_number()    2.oracle需要排序(为了排序,单独写了一个子查询),但是在sqlserver 中可以省略该排序的子查询  因为sqlserver中可以通过over直接排序


sqlserver2012之后支持:	
offset fetch next only


select * from student  oreder by sno 
offset (页数-1)*页面大小+1  rows fetch next 页面大小  rows only ;


(n-1)*10+1    ---  n*10 

mysql从0开始计数,Oracle/sqlserver 从1开始计数

二.SQL到Java联系(具体分页实现)

2.1 需要5个属性

2.2 数据总数(查数据库)

select count(*)..

2.3 页面大小(用户自定义)

每个页面显示的数据条数(20)

2.4 总页数(程序自动计算)

  1. 总页数 = 100/20 =数据总数/页面大小
  2. 总页数 = 103/20 = 数据总数/页面大小+1
  3. 总页数 = 数据总数%页面大小 == 0? 数据总数/页面大小 : 数据总数/页面大小+1;

2.5 当前页(页码)

2.6 当前页的对象集合 (查数据库,分页sql)

  1. 每页所显示的所有数据 (10个人信息)
  2. List<Student>

三.项目构造(基于上一个项目的框架完善

3.1 给DBUtil工具类增加查询总数方法

//	查询总数
	public static int getTotalCint(String sql) {
		int count = -1;
		try {
			pstmt = createPreparedStatement(sql, null);
			rs = pstmt.executeQuery();
			if (rs.next()) {
				count = rs.getInt(1);
			}
			return count;
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			closeAll(rs, pstmt, connection);	
			return count;
		}
	}

3.2 给dao层,service层添加方法(并在对应实现类具体实现)

3.2.1查询总数据数方法

3.2.2 查询每一页学生方法

3.2.3 具体代码(只有新增代码,前面有所属包)

package org.student.dao;

import org.student.entity.Student;

public interface IStudentDao {
//	查询总数据数
	public int getTotalCount();
//	查询每一页所有学生
//	currentPage:当前页     pageSize:页面大小
	public List<Student> queryStudentsByPage(int currentPage,int pageSize);
package org.student.dao.impl;
//	查询总数据量
	@Override
	public int getTotalCount() {
		String sql = "select count(*) from student";
		return DBUtil.getTotalCint(sql);
	}
//	返回每一次页面的数据集合
	@Override      //	currentPage:当前页     pageSize:页面大小
	public List<Student> queryStudentsByPage(int currentPage, int pageSize) {
		String sql = "SELECT * FROM student LIMIT ?,?";
		Object[] params = {currentPage*pageSize,pageSize};
		ResultSet rs = DBUtil.executeQuery(sql, params);
		List<Student> students = new ArrayList<Student>();
		try {
			while (rs.next()) {
				int no = rs.getInt("sno");
				String name = rs.getString("sname");
				int age = rs.getInt("sage");
				String address = rs.getString("saddress");
				Student student = new Student(no, name, age,address);	
				students.add(student);
			}
			return students;
		} catch (SQLException e) {
			e.printStackTrace();
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			DBUtil.closeAll(DBUtil.rs, DBUtil.pstmt,DBUtil.connection );
		}
		return students;
	}
package org.student.service;

public interface IStudentService {
	public List<Student> queryStudentsByPage(int currentPage ,int pageSize);
	public int getTotalCount();
package org.student.service.impl;

// 业务逻辑层:逻辑性增删改查( 增:查+增),对dao层进行组装
public class StudentServiceImpl implements IStudentService{
	
		IStudentDao studentDao = new StudentDaoImpl();
		//查询当前页的数据集合
		@Override
		public List<Student> queryStudentsByPage(int currentPage, int pageSize) {
			return studentDao.queryStudentsByPage(currentPage, pageSize);
		}
		//查询数据总条数
		@Override
		public int getTotalCount() {
			return studentDao.getTotalCount();
		}

3.3 分页的帮助类(Page)

  1. 因为分页的元素过多,所以建一个类来存放数据
  2. 这个类当做实现类,所以建在entity
  3. 里面的元素就是之前的5个元素
  4. 因为总页数,不需要赋值,需自动计算,所以去掉setter方法
  5. 再有总数据数,页面大小后就可以计算总页数,所以将对其赋值放在setPageSize()里:
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
//		自用计算总页数 = 数据总数%页面大小==0?数据总数/页面大小 : 数据总数/页面大小+1
		this.totalPage = this.totalCount%this.pageSize == 0 ? this.totalCount/this.pageSize :this.totalCount%this.pageSize+1;
	}

6.但是要注意赋值顺序,需要先赋总页数值,再赋页面大小值,也可以改进:

	private void setTotalPage() {
//		自用计算总页数 = 数据总数%页面大小==0?数据总数/页面大小 : 数据总数/页面大小+1
//        排除页面大小为0,出现异常情况
		if(this.pageSize != 0){
		this.totalPage = this.totalCount%this.pageSize == 0 ? this.totalCount/this.pageSize :this.totalCount%this.pageSize+1;
		}
	}
	public void setTotalCount(int totalCount) {
		this.totalCount = totalCount;
		this.setTotalPage();
	}
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
		this.setTotalPage();

	}
  1. 具体代码
package org.student.entity;
// 分页的帮助类
import java.util.List;
public class Page {
//  当前页
	private int currentpage;
//	页面大小
	private int pageSize;
//	总数据
	private int totalCount;
//	总页数,不需要赋值,需自动计算,去掉setter方法
	private int totalPage;
//	当前页的数据集合
	private List<Student> students;
	public Page() {
	}
	public Page(int currentpage, int pageSize, int totalCount, int totalPage, List<Student> students) {
	super();
	this.currentpage = currentpage;
	this.pageSize = pageSize;
	this.totalCount = totalCount;
	this.totalPage = totalPage;
	this.students = students;
}
	public int getCurrentpage() {
		return currentpage;
	}
	public void setCurrentpage(int currentpage) {
		this.currentpage = currentpage;
	}
	public int getPageSize() {
		return pageSize;
	}
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
//		自用计算总页数 = 数据总数%页面大小==0?数据总数/页面大小 : 数据总数/页面大小+1
		this.totalPage = this.totalCount%this.pageSize == 0 ? this.totalCount/this.pageSize :this.totalCount%this.pageSize+1;
	}
	public int getTotalCount() {
		return totalCount;
	}
	public void setTotalCount(int totalCount) {
		this.totalCount = totalCount;
	}
	public int getTotalPage() {
		return totalPage;
	}
	public List<Student> getStudents() {
		return students;
	}
	public void setStudents(List<Student> students) {
		this.students = students;
	}
}

3.4 新建分页servlet(QueryStudentByPage.java)

3.4.1 给Page对象传值,放入request中

3.4.2 配置Web.xml(先获取值,再展示值)

<welcome-file>QueryStudentByPage</welcome-file>

package org.student.servlet;

public class QueryStudentByPage extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		
		IStudentService service = new StudentServiceImpl();
//		将分页所需的五个字段(实际只有一个,所以需要组装4个)
		Page pages = new Page();
//		数据总数
		int totalCount = service.getTotalCount();
//		1. pages赋值totalCount
		pages.setTotalCount(totalCount);
//		第一次进入,获取的是第几页,从0页开始
		String cPage = request.getParameter("currentPage");
		if (cPage == null) {
			cPage = "0";
		}
		int currentPage = Integer.parseInt(cPage);
//		2. pages赋值currentPage
		pages.setCurrentpage(currentPage);
//		页面大小,先手动给定值
		int pageSize = 5;
//		3. pages赋值pageSize,注意顺序
		pages.setPageSize(pageSize);
//		获取动态集合
		List<Student> students =  service.queryStudentsByPage(currentPage, pageSize);
//		4. pages赋值 List<Student> students
		pages.setStudents(students);
//		存入数据
		request.setAttribute("pages", pages);
//		因为request中有数据,通过请求转发(重定向丢失request),跳转到index.jsp显示数据
		request.getRequestDispatcher("index.jsp").forward(request, response);
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request, response);
	}
}

3.5 index.jsp(展示主要代码)

  1. 代码里思维是从0页开始
  2. 假设一共10页,则有0–9页,下来看代码
  3. 所以 当pages.getCurrentpage() ==pages.getTotalPage()-1是到达尾页
  4. 所以 pages.getCurrentpage() ==0是跳转首页
  5. 所以pages.getTotalPage()-1是跳转尾页
<body>
	<table border = "1px">
		<tr>
				<th>学号</th>
				<th>姓名</th>
				<th>年龄</th>		
				<th>操作</th>	
		</tr>
		<%
		// 从QueryStudentByPage 跳转过来的(在xml里改过了),
		//需要先查询,再显示数据,因为这里要获取数据
		// 获取request域里的数据,Object类型转换
		Page pages = (Page) request.getAttribute("pages");
		for(Student student : pages.getStudents() ){
			%>
					<tr>
					<!-- 学号跳转查询此人信息 -->
						<th><a href="QueryStudentBySnoServlet?sno=<%=student.getSno() %>"><%=student.getSno() %></a></th>
						<th><%=student.getSname() %></th>
						<th><%=student.getSage() %></th>
						<th><a href="DeleteStudentServlet?sno=<%=student.getSno() %>">删除</a></th>
					</tr>
				<%	
		}
		%>
		
	</table>
<a href="add.jsp">新增</a>
	   <%
				if(pages.getCurrentpage() ==pages.getTotalPage()-1){ //尾页
		%>		
		       <a href="QueryStudentByPage?currentPage=0">首页</a>
			   <a href="QueryStudentByPage?currentPage=<%=pages.getCurrentpage()-1%>    ">上一页</a>
		<% 
				}
				else if(pages.getCurrentpage() ==0){//首页
		%>	
		    <a href="QueryStudentByPage?currentPage=<%=pages.getCurrentpage()+1%> ">下一页</a>
			<a href="QueryStudentByPage?currentPage=<%=pages.getTotalPage()-1%>">尾页</a>
		<%		
			}
				else{//中间
		%>		
			<a href="QueryStudentByPage?currentPage=0">首页</a>
			<a href="QueryStudentByPage?currentPage=<%=pages.getCurrentpage()-1%>    ">上一页</a>
			<a href="QueryStudentByPage?currentPage=<%=pages.getCurrentpage()+1%> ">下一页</a>
			<a href="QueryStudentByPage?currentPage=<%=pages.getTotalPage()-1%>">尾页</a>
		<%			
				}
		%>
  <!--  没有完善的手动输入一页有多少条数据 功能
		<br/>
		每页显示
		<select>
		
			<option value="3">3</option>
			<option value="5">5</option>
			<option value="10">10</option>
		</select>-->
</body>
发布了22 篇原创文章 · 获赞 2 · 访问量 767

猜你喜欢

转载自blog.csdn.net/qq_43542795/article/details/104072549