分页逻辑实现_思维态度行动的博客-程序员宅基地

技术标签: JavaEE  项目  

分页简介

用来将数据分割成多个部分来分页面展示。

什么时候用?

数据量达到一定的时候,就需要使用分页来进行数据分割。要不然可能会面临以下问题:

  • 客户端一次性显示太多数据会影响到用户的体验,比如很难找到客户想要的信息,以及加载页面数据过慢。
  • 对于服务端来说,一次性传送的数据过多,可能造成内存溢出。

分页的分类

分页分为真分页和假分页:

  • 真分页(物理分页):
    在mysql中使用select * from table where …limit start , size(在oracle中复杂些)
    (page_num 代表具体第多少页,pages代表每页有多少条数据)
    第一个参数start代表(page_num-1)*pages
    第二个参数是 pages,即页面数据量最大是多少
    还有limit如果后面只有一个参数,则相当于0,num即0行到num-1行
  • 假分页(逻辑分页):
    直接使用select * from table where …
    这样将所有数据查询出来存放到内存中,每次需要查询时直接从内存中去取出相应索引区间的数据

区别

真分页相比于假分页不会造成内存溢出,但翻页的数据相比于假分页又慢,所以根据实际情况选择分页方式,如果数据量不大,可以考虑使用假分页使翻页速度加快。

实现

假分页

假分页实际上使用List去存储所有查询出的值,再用subList方法获取两个索引之间的数据。

先在dao层,创建StudentMapper接口

List<Student> queryStudentsByArray();

再创建StudentMapper.xml文件,编写查询语句:

<select id="queryStudentsByArray" resultType="Student">
   select * from student
</select>

然后定义Service接口并定义分页方法:

List<Student> queryStudentsByArray(int currPage, int pageSize);

再在Servlce实现类中重写该方法:

@Override
public List<Student> queryStudentsByArray(int currPage, int pageSize) {
    
     List<Student> students = studentMapper.queryStudentsByArray();
     // 从第几条数据开始
     int firstIndex = (currPage - 1) * pageSize;
     // 到第几条数据结束
     int lastIndex = currPage * pageSize;
     return students.subList(firstIndex, lastIndex);
}

这里控制器和前台就根据这个方法来编写。

真分页

这里以我自己在一个个人博客后台管理type和tag的分页为例:
先封装一个Page类,用来做分页(为了简便):

package com.yuer.entity;

import java.util.ArrayList;
import java.util.List;

// 进行分页的工具类
// 使用泛型的原因是可能对不同类型进行分页
// 在first,last,start的get方法中,进行一些处理,保证这三个字段正确
public class Page<T> {
    

	// 这里存放的每次查出来的一页内容
	private List<T> content = new ArrayList<>();

	// 当前页数 默认为1
	private int page = 1;

	// 总页数
	private int totalPages = 0;

	// 这个等于(page - 1) * size,代表该显示多少条数据的第一个索引
	private int start = 0;
	
	// 默认为4
	private int size = 4;

	// 当前是不是首页,默认为true
	private boolean first = true;

	// 当前是不是尾页,默认是false
	private boolean last = false;

	public List<T> getContent() {
    
		return content;
	}

	public void setContent(List<T> content) {
    
		this.content = content;
	}

	public int getPage() {
    
		return page;
	}

	public void setPage(int page) {
    
		this.page = page;
	}

	public int getTotalPages() {
    
		return totalPages;
	}

	public void setTotalPages(int totalPages) {
    
		this.totalPages = totalPages;
	}

	public int getStart() {
    
		this.start = (page - 1) * size;
		return start;
	}

	public void setStart(int start) {
    
		this.start = start;
	}
	

	public int getSize() {
    
		return size;
	}

	public void setSize(int size) {
    
		this.size = size;
	}

	public boolean isFirst() {
    
		if (page != 1) {
    
			this.first = false; 
		} else {
    
			this.first = true; 
		}
		
		return first;
	}

	public void setFirst(boolean first) {
    
		this.first = first;
	}

	public boolean isLast() {
    
		if (page != totalPages) {
    
			this.last = false; 
		} else {
    
			this.last = true; 
		}
		return last;
	}

	public void setLast(boolean last) {
    
		this.last = last;
	}

	public Page() {
    
		start = (page - 1) * size;
	}

	

}

接下来是显示层(只截取了关键部位):

<!--中间内容-->
  <div  class="m-container-small m-padded-tb-big main">
    <div class="ui container">
      <div class="ui success message" th:unless="${#strings.isEmpty(message)}">
        <i class="close icon"></i>
        <div class="header">提示:</div>
        <p th:text="${message}">恭喜,操作成功!</p>
      </div>
      <table class="ui compact  table">
        <thead>
          <tr>
            <th></th>
            <th>名称</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr th:each="type,iterStat : ${page.content}">
            <td th:text="${iterStat.count}">1</td>
            <td th:text="${type.typeName}">刻意练习清单</td>
            <td>
              <a href="#" th:href="@{/admin/types/{id}/input(id=${type.id})}" class="ui mini teal basic button">编辑</a>
              <a href="#" th:href="@{/admin/types/{id}/delete(id=${type.id})}" class="ui mini red basic button">删除</a>
            </td>
          </tr>
        </tbody>
        <tfoot>
          <tr>
            <th colspan="6" >
            <!-- ${
    page.totalPages}>1代表看总页数是否大于1,大于则显示这两个上一页,下一页 -->
              <div class="ui mini pagination menu" th:if="${page.totalPages}>1">
              <!-- 这里page.first为是否是第一页,是不显示,同理page.last
              page.number代表当前页数 -->
                <a href="#" th:href="@{/admin/types/{page}(page=${page.page}-1)}" class="  item" th:unless="${page.first}">上一页</a>
                <a href="#" th:href="@{/admin/types/{page}(page=${page.page}+1)}" class=" item" th:unless="${page.last}">下一页</a>
              </div>
              <a href="#" th:href="@{/admin/types/input}"  class="ui mini right floated teal basic button">新增</a>
            </th>
          </tr>
        </tfoot>
      </table>
    </div>
  </div>

接下来是Controller层:

package com.yuer.controller.admin;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.yuer.entity.Page;
import com.yuer.entity.Type;
import com.yuer.service.ITypeService;

@Controller
@RequestMapping("/admin")
public class TypeController {
    

	@Autowired
	private ITypeService typeService;

	// 这个是默认的访问,不带参数
	@GetMapping("/types")
	public String typesDefault(Model model) {
    
		Page<Type> page = getPage(-1, false);
		model.addAttribute("page", page);

		return "admin/types";
	}

	// page代表当前页数,当按上一页下一页会触发这个方法
	@GetMapping("/types/{page}")
	public String types(@PathVariable Integer page, Model model) {
    
		Page<Type> page1 = getPage(page, true);
		model.addAttribute("page", page1);

		return "admin/types";
	}

	

	public Page<Type> getPage(Integer page, boolean flag) {
    
		// 先 new Page
		Page<Type> page1 = new Page<Type>();

		// 先查出数据条数,再计算得出多少页
		int total = typeService.getTotal();
		int totalPages;
		if (total % page1.getSize() == 0) {
    
			 totalPages = total / page1.getSize();
		} else {
    
			 totalPages = total / page1.getSize() + 1;
		}
		page1.setTotalPages(totalPages);

		if (flag) {
    
			page1.setPage(page);
		}

		page1.setContent(typeService.listTypeByParam(page1.getStart(), page1.getSize()));

		return page1;
	}

}

控制层中的typesDefault方法代表首次进入分类管理,此时只需要显示第一页即可,即在Page类中配置好的默认值,而types方法则是点击上一页下一页时触发的方法,此时会传过来当前的页数,然后set进Page类中,此时不同的数据就会更新。

此时看typeService.listTypeByParam(page1.getStart(), page1.getSize()):这个方法是用来分页的关键方法:

@Transactional
	@Override
	public List<Type> listTypeByParam(int start, int size) {
    
		return typeDao.listTypeByParam(start, size);
	}

这个直接到mapper.xml文件中看此方法sql语句:

<!-- 这里返回值可能注入错误,需要进行Map映射 -->
	<select id ="listTypeByParam" resultMap="TypeMap" parameterType="Integer">
		select id,type_name from hi_type order by id limit #{
    start}, #{
    size}
	</select>
	
	<resultMap type="Type" id="TypeMap">
		<result property="id" column="id"/>
		<result property="typeName" column="type_name"/>
		
	</resultMap>

总结一下:没点击上一页下一页之前默认显示0到size-1条数据,然后点击上一页下一页触发翻页功能时,就在Page类中注入相应的值,取其中的值时,就会同步的发生变化,最后通过mysql的简便分页方法limit start,size方法完成。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/codingno1/article/details/104423663

智能推荐

简单的 菜单当前选中 解决思路-程序员宅基地

任何一个网站,都是离不开导航或菜单,为了让用户清楚的知道自己身处何方,“面包屑”路径也是经常被的应用的。但是,当前所属菜单的选中样式也是同样是经常被采用的。 例如我们经常用到的google音乐的这种样式:。 像这种菜单,基本每个页面都会出现的,我们肯定会做一个控件来到处引用或者放到母版页里,这样就会出现选中的问题。呵呵,当然实现的方法也是多..._当前选中项

负载均衡设计-程序员宅基地

最近要搭建一个高并发的网站。所以,得设计负载均衡这一块。从大的方向上讲,负载均衡分为硬负载均衡,和软负载均衡。下面依次简要说明一下:硬负载均衡:硬负载均衡,也就是使用专用的负载均衡设备。主流的硬负载均衡器有如下几种:F5:最主流的硬负载均衡器。便宜的20万以上,贵的100多万。深信服:乞丐版低配12万元起价。A10:基本都在100万元以上。Array:16-100万。看..._负载均衡 分数怎样设计

利用随机点产生一维的线性拟合的简单算法(matlab简单的ransac算法)_matlab 随机点拟合一条线-程序员宅基地

一维的线性拟合算法(matlab简单的ransac算法)1.我们初学matlab的时候,肯定会接触差值和拟合这两个知识点,因为这两个知识点对数据的而处理非常有用,今天呢我们来一起探讨一下如何从所得到的数据来实现简单的一维线性拟合。2.下列步骤是我们此次算法的主要思路:Step 1 随机选取数据中的两个点,确定直线方程;Step 2 计算数据点到直线的距离,统计距离小于一定阈值的点的数目记..._matlab 随机点拟合一条线

MAC Homebrew 指令安装&卸载_homebrew安装 the xcode command line tools will be in-程序员宅基地

1.安装brew/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"MacBook-Pro:.Trash sysadmin$ /usr/bin/ruby -e "$(curl -fsSL https://raw.github..._homebrew安装 the xcode command line tools will be installed.

两个kernel.org国内镜像-程序员宅基地

在家里访问kernel.org巨慢,好在不用git clone整个仓库,只是下载最新代码包而已,即使如此,近百M的东西用几十K的速度下也太蛋疼了。kernel.org在国内的镜像似乎不多,到sohu和163上看了下,没有kernel.org。最后找到了北京交通大学和清华大学的镜像。前者速度不快,下几分钟就断线了,后者速度不错。http://mirror.bjtu.edu.c

随便推点

unbuntu 12.04新安装qt5.4配置及问题解决。_ld_library_path=/opt/qt515/lib qt_plugin_path=/opt-程序员宅基地

1、设置环境变量。执行gedit ~/.bashrc 添加如下内容:QTDIR=/usr/local/Trolltech/Qt-4.8.6/PATH=$QTDIR/bin:$PATHMANPATH=$QTDIR/doc/man:$MANPATHLD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATHexport QTDIR PATH MANPA_ld_library_path=/opt/qt515/lib qt_plugin_path=/opt/qt515/plugins

idea Debug启动不了-程序员宅基地

idea 启动 Debug 的时候一直启动不了一直在转圈,解决:ctrl + shift + F8 选中 Java Method Breajpoints如果还不能解决,先去掉断点,待Debug启动成功后再打上断点测试,OK...

OpenGL基础31:混合_opengl边缘干扰-程序员宅基地

在很多游戏场景中,地面往往都不是完全干净和平坦的,如果是草坪,那么肯定会有一些长得比较高的杂草,而对于沙地,往往总会有一些奇形怪状的石头等,一般来讲确实可以用模型,但是贴图也是一个不错的选择一、Alpha值考虑给地面铺上“石头”:注意如果想加载这种纹理,最好保证空白的部分是透明的而并非为白底!前面讨论过颜色的属性:RGB,其实颜色还有一个属性A代表为透明度也就是说:RGBA才是一个表示颜色的“完全体”,如果想渲染一些半透明的材质,就必须要考虑到透明度这一属性,就如上面的石头..._opengl边缘干扰

使用ajax获取后台传过来的值乱码?!这么做,轻松搞定!!_ajax后台取值为乱码_我要吃一条街的博客-程序员宅基地

今天用ajax的时候发现后台传过来的值乱码!!!!可是我明明写了字符过滤器呀!然后经过我的一顿乱操作,它终于不乱码了!!!怎么好的???答案就是我在后台controller的方法的@Request Mapping中加了一个属性 produces@RequestMapping(value = "/a3",produces = "text/html;charset=UTF-8;")..._ajax后台取值为乱码

&lt;C++精英内参-程序员高效指南&gt;-4搭配VS的好用工具-程序员宅基地

如果你用VS多年,就一定要知道visual assist,这个工具是一个番茄标志,最大的便利是可以迅速帮我们区分变量名,类名,API等多种代码,比起VS原生的干巴巴的界面,VS让你的开发生动了许多。当然,除了VA,还有很多工具,你还知道哪些?用VS开发的,一定要装VA. 代码写爽了,就会久坐,那么腰酸就不可避免了,如何保护我们的腰?欢迎访问我的博客,送你五本职场精英必看的职场书...

Linux常用命令_touch config_是草莓味的啊的博客-程序员宅基地

目录一.Linux终端命令1.为什么要学习终端命令2.终端命令的格式3.查阅命令及常用选项的帮助信息4.Linux常用终端命令简介5.Linux常用终端命令扩展①.ls命令②.cd命令③.touch命令④.mkdir命令⑤.rm命令6.Linux拷贝和移动命令扩展①.tree命令②.cp命令③.mv命令7.Linux文件内容命令扩展①.cat命令②.more命令③.grep命令8.Linux其他命令扩展①.echo文字内容②.重定向>和>>③.管道|9.Linux远程管理常用命令扩展①.s_touch config