`
junherry
  • 浏览: 97543 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

几种分页方式分析

阅读更多

转自链接 http://www.cnblogs.com/wllyy189/articles/1237478.html

 

一.逻辑分页
 
1.逻辑分页的第一种方式,利用ResultSet的滚动分页。步骤如下:
 a.根据条件sql查询数据库。
 b.得到ResultSet的结果集,由于ResultSet带有游标,因此可以使用其next()方法来指向下一条记录。
 c.利用next()方法,得到分页所需的结果集。

 这种分页方式依靠的是对结果集的算法来分页,因此通常被称为“逻辑分页”。

 代码如下:

/**
 * TestPageResultSetDAO.java
 *
 * Copyright 2008. All Rights Reserved.
 */

package com.cosmow.pageresultset.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.cosmow.pageresultset.entity.Bars;

/**
 * TODO dao class TestPageResultSetDAO
 * 
 * Revision History
 * 
 * 2008-7-7,Cosmo,created it
 */

public class TestPageResultSetDAO {

    private final String FIND_BARS_PAGE = "SELECT * FROM YYBARS ORDER BY id";

    /**
     * 提供JDBC连接方法,返回一个Connection的实例
     * 
     * @return
     * @throws SQLException
     */

    private Connection getConnection() throws SQLException {
        try {
            final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
            final String user = "store";
            final String password = "store_password";
            Class.forName("oracle.jdbc.driver.OracleDriver");
            Connection con = DriverManager.getConnection(url, user, password);
            return con;
        }
 catch (ClassNotFoundException e) {
            throw new SQLException(e.getMessage());
        }

    }


    /**
     * 逻辑分页方法一,该方法使用移位(rs.next)来进行
     * 
     * @param currentPage
     *            当前页
     * @param showRows
     *            一页显示的数据量
     */

    public List<Bars> pageListOne(int currentPage, int showRows) {
        Connection con = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        ArrayList<Bars> resultList = new ArrayList<Bars>();
        try {
            con = getConnection();
            ps = con.prepareStatement(FIND_BARS_PAGE);
            rs = ps.executeQuery();
            // 过滤结果集的变量
            int skipBegin = (currentPage - 1) * showRows;
            int skipEnd = currentPage * showRows;
            // 翻页计数器
            int currentNum = 0;
            // 当返回结果集中有记录时
            while (rs.next()) {
                // 以下情况将保证在结果集中有记录时的应用
                if (currentNum >= skipBegin && currentNum < skipEnd) {
                    Bars bar = new Bars();
                    bar.setId(rs.getLong("id"));
                    bar.setName(rs.getString("name"));
                    bar.setType(rs.getInt("type"));
                    bar.setCreatorId(rs.getLong("creator_id"));
                    resultList.add(bar);
                    if (currentNum == skipEnd - 1)
                        break;
                }

                currentNum++;
            }

        }
 catch (SQLException e) {
            e.printStackTrace();
        }
 finally {
            try {
                if (rs != null)
                    rs.close();
                if (ps != null)
                    ps.close();
                if (con != null)
                    con.close();
            }
 catch (SQLException e) {
                e.printStackTrace();
            }

        }

        return resultList;
    }

}


2.逻辑分页的第二种方式
利用Scrollable ResultSets(可滚动结果集合)来快速定位到某个游标所指定的记录行,所使用的是ResultSet的absolute()方法。
改进代码如下:

/**
 * TestPageResultSetDAO.java
 *
 * Copyright 2008. All Rights Reserved.
 */

package com.cosmow.pageresultset.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.cosmow.pageresultset.entity.Bars;

/**
 * TODO dao class TestPageResultSetDAO
 * 
 * Revision History
 * 
 * 2008-7-7,Cosmo,created it
 */

public class TestPageResultSetDAO {

    private final String FIND_BARS_PAGE = "SELECT * FROM YYBARS ORDER BY id";
    
    /**
     * 提供JDBC连接方法,返回一个Connection的实例
     * 
     * @return
     * @throws SQLException
     */

    private Connection getConnection() throws SQLException {
        try {
            final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
            final String user = "store";
            final String password = "store_password";
            Class.forName("oracle.jdbc.driver.OracleDriver");
            Connection con = DriverManager.getConnection(url, user, password);
            return con;
        }
 catch (ClassNotFoundException e) {
            throw new SQLException(e.getMessage());
        }

    }


    /**
     * 逻辑分页方法二,使用absolute()方法分页
     * 
     * @param currentPage
     *            当前页
     * @param showRows
     *            一页显示的数据量
     */

    public List<Bars> pageListTwo(int currentPage, int showRows) {
        Connection con = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        ArrayList<Bars> resultList = new ArrayList<Bars>();
        try {
            con = getConnection();
            ps = con.prepareStatement(FIND_BARS_PAGE);
            rs = ps.executeQuery();

            // 过滤结果集的变量
            int skipBegin = (currentPage - 1) * showRows;
            int skipEnd = currentPage * showRows;
            // 利用rs.absolute进行定位
            if (!rs.absolute(skipBegin))
                return resultList;
            // 当返回结果集中有记录时
            while (rs.next()) {
                // 以下情况将保证在结果集中有记录时的应用
                if (skipBegin < skipEnd) {
                    Bars bar = new Bars();
                    bar.setId(rs.getLong("id"));
                    bar.setName(rs.getString("name"));
                    bar.setType(rs.getInt("type"));
                    bar.setCreatorId(rs.getLong("creator_id"));
                    resultList.add(bar);
                    if (skipBegin == skipEnd - 1)
                        break;
                }

            }

        }
 catch (SQLException e) {
            e.printStackTrace();
        }
 finally {
            try {
                if (rs != null)
                    rs.close();
                if (ps != null)
                    ps.close();
                if (con != null)
                    con.close();
            }
 catch (SQLException e) {
                e.printStackTrace();
            }

        }

        return resultList;
    }

}


虽然和第一种方式区别不大,单效率比ResultSet滚动要好,但是absolute()方法并不是所有jdbc驱动都支持。
可用如下代码测试当前jdbc驱动是否支持可滚动结果集:

int type = rs.getType();
if (type == ResultSet.TYPE_SCROLL_INSENSITIVE || type == ResultSet.TYPE_SCROLL_SENSITIVE)
    System.out.println("Result set is scrollable");
else
    System.out.println("Result set is not scrollable");

二.物理分页
利用数据库本身的一些特性来分页。即:利用了数据库对sql语法的优化,提高分页性能。
1.针对Oracle数据库
步骤如下:
a.根据所使用的数据库特性来组织sql进行分页。
b.每次跳转页面的sql查询都不相同。
 通用的sql分页方式,“限制行数结果集的倒序”分页,步骤如下:
 (1).取得符合条件的所有结果集中可以唯一标识的Key值(通常是主键),并正向排序。
 (2).利用数据库提供的特殊方法进行“最大结果集”的限制(在Oracle中使用rownum, sql server中使用top, mysql中使用limit...),
 该“最大结果集”指包含当前所处页的所有记录数,“最大结果集”应该只包含惟一的Key值。
 (3).对步骤(2)中的“最大结果集”进行逆序,并取得“显示当前页显示数量的结果集”,该结果集中只包含惟一的Key值。
 (4).通过步骤(3)中所取得的Key值取得显示数据,该显示数据就是当前页应该显示的数据。

代码如下:

/**
 * TestPageResultSetDAO.java
 *
 * Copyright 2008. All Rights Reserved.
 */

package com.cosmow.pageresultset.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.cosmow.pageresultset.entity.Bars;

/**
 * TODO dao class TestPageResultSetDAO
 * 
 * Revision History
 * 
 * 2008-7-7,Cosmo,created it
 */

public class TestPageResultSetDAO {

    //针对Oracle
    private final String FIND_BARS_ORACLE = "select b3.* from "
            + "(select b1.id from "
            + "(select b.id from yybars b where rownum <= ? order by b.id desc) b1 "
            + "where rownum <= ? order by b1.id desc) b2, "
            + "yybars b3 where b2.id = b3.id order by b2.id";
    
    /**
     * 提供JDBC连接方法,返回一个Connection的实例
     * 
     * @return
     * @throws SQLException
     */

    private Connection getConnection() throws SQLException {
        try {
            final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
            final String user = "store";
            final String password = "store_password";
            Class.forName("oracle.jdbc.driver.OracleDriver");
            Connection con = DriverManager.getConnection(url, user, password);
            return con;
        }
 catch (ClassNotFoundException e) {
            throw new SQLException(e.getMessage());
        }

    }


    /**
     * 物理分页方法一针对Oracle,使用sql语句的id查询来进行
     * 
     * @param currentPage
     *            当前页
     * @param showRows
     *            一页显示的数据量
     */

    public List<Bars> pageListThree(int currentPage, int showRows) {
        Connection con = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        ArrayList<Bars> resultList = new ArrayList<Bars>();
        try {
            con = getConnection();
            ps = con.prepareStatement(FIND_BARS_ORACLE);
            //传入参数,第一个参数标示包含该页总共有几条数据
            ps.setInt(1, showRows * currentPage);
            //第二个参数标示将取得在第一个参数所指定的数据中应该显示的数据
            ps.setInt(2, showRows);
            rs = ps.executeQuery();
            // 当返回结果集中有记录时
            while (rs.next()) {
                Bars bar = new Bars();
                bar.setId(rs.getLong("id"));
                bar.setName(rs.getString("name"));
                bar.setType(rs.getInt("type"));
                bar.setCreatorId(rs.getLong("creator_id"));
                resultList.add(bar);
            }

        }
 catch (SQLException e) {
            e.printStackTrace();
        }
 finally {
            try {
                if (rs != null)
                    rs.close();
                if (ps != null)
                    ps.close();
                if (con != null)
                    con.close();
            }
 catch (SQLException e) {
                e.printStackTrace();
            }

        }

        return resultList;
    }

}

2.针对MySQL数据库
在MySQL数据库中offset关键字的意思是"越过",而limit关键字的意思是“限制”,利用这两者结合可轻松分页。
(1)取得符合条件的结果集,包含全字段。
(2)利用offset关键字越过一段结果集(被越过的结果集就是"(当前页 - 1) * 一页显示数")。
(3)利用limit关键字限制取得一段结果集(被限制取得的结果集就是一页显示数)

代码如下:

/**
 * TestPageResultSetDAO.java
 *
 * Copyright 2008. All Rights Reserved.
 */

package com.cosmow.pageresultset.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.cosmow.pageresultset.entity.Bars;

/**
 * TODO dao class TestPageResultSetDAO
 * 
 * Revision History
 * 
 * 2008-7-7,Cosmo,created it
 */

public class TestPageResultSetDAO {
    
    private final String FIND_BARS_MYSQL = "select * from yybars order by id limit ? offset ?";
    

    /**
     * 提供JDBC连接方法,返回一个Connection的实例
     * 
     * @return
     * @throws SQLException
     */

    private Connection getConnection() throws SQLException {
        try {
            final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
            final String user = "store";
            final String password = "store_password";
            Class.forName("oracle.jdbc.driver.OracleDriver");
            Connection con = DriverManager.getConnection(url, user, password);
            return con;
        }
 catch (ClassNotFoundException e) {
            throw new SQLException(e.getMessage());
        }

    }

    
    /**
     * 物理分页方法二针对mysql,使用sql语句的limit和offset来进行分页
     * 
     * @param currentPage
     *            当前页
     * @param showRows
     *            一页显示的数据量
     */

    public List<Bars> pageListFour(int currentPage, int showRows) {
        Connection con = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        ArrayList<Bars> resultList = new ArrayList<Bars>();
        try {
            con = getConnection();
            ps = con.prepareStatement(FIND_BARS_MYSQL);
            //传入参数,第一个参数表示显示几条记录(limit关键字的含义)
            ps.setInt(1, showRows);
            //第二个参数表示丢弃几条记录(offset关键字的含义)
            ps.setInt(2, showRows * (currentPage - 1));
            rs = ps.executeQuery();
            // 当返回结果集中有记录时
            while (rs.next()) {
                Bars bar = new Bars();
                bar.setId(rs.getLong("id"));
                bar.setName(rs.getString("name"));
                bar.setType(rs.getInt("type"));
                bar.setCreatorId(rs.getLong("creator_id"));
                resultList.add(bar);
            }

        }
 catch (SQLException e) {
            e.printStackTrace();
        }
 finally {
            try {
                if (rs != null)
                    rs.close();
                if (ps != null)
                    ps.close();
                if (con != null)
                    con.close();
Codehighlight
分享到:
评论

相关推荐

    几种数据库分页查询的区别

    Oracle、MYSQL、sqlserver和DB2分页查询 分页查询

    ACCESS数据库大数据量分页的几种方法比较及测试结果分析

    ACCESS 数据库大数据量分页的几种方法比较及测试结果分析 本文解决的问题:1.ACCESS 是否存在更有效率的分页方法?2.现有 ACCESS 大数据量 10 万条数据分页的效率测试3.ACCESS 的数据承载量到底有多大? ACCESS ...

    oracle认证详解Oracle的几种分页查询语句

    ### Oracle认证详解:Oracle的几种分页查询语句 #### 分页查询背景及重要性 在数据库管理系统(DBMS)中,特别是在Oracle这样的大型关系型数据库中,分页查询是一种非常实用的技术。它允许用户根据需求获取特定...

    C#分页结构分析信息文档

    【C#分页结构分析信息文档】 在.NET框架中,特别是在C#编程环境中,分页是一种常见的数据处理技术,用于处理大量数据时提供高效的用户体验。它允许用户逐步加载和查看数据,而不是一次性加载所有记录,这有助于降低...

    sql的分页处理,海量数据的提取效率分析

    首先,我们要了解SQL的几种常见的分页方式。最基础的是使用`OFFSET`和`FETCH`关键字,这种方法直观且易于理解,但当数据量巨大时,由于需要跳过大量行,性能会显著下降。另一种常见方法是基于`ROW_NUMBER()`窗口函数...

    电子书TXT分页

    分页通常有以下几种方法: 1. 字数分页:根据每页预设的字数来切割文本,例如设定每页显示500字,当达到这个字数时自动换页。这种方法简单直观,但可能因字体大小、排版差异导致实际显示的页面内容不一致。 2. ...

    dwr分页源码,dwr分页源码

    在Web应用中,分页是一种常见的数据展示方式,尤其是当处理大量数据时,它可以提高用户体验并减轻服务器负载。DWR结合Ajax技术可以提供流畅的分页体验,用户无需等待整个页面加载,只需加载分页内容即可。 首先,...

    分页代码,实现分页的两种写法

    分页技术是一种用于处理大数据量显示的技术,通过限制每次查询的数据数量,将数据分为多页展示,不仅可以提升用户体验,还能有效减轻服务器压力。 #### 原理 1. **计算总记录数**:首先,需要获取数据库中符合条件...

    QTableWidget,QTableView分页的分页栏使用demo

    在“MultiPageDemo”项目中,可能包含了一个实现上述功能的示例代码,你可以通过分析和运行这个示例来更好地理解分页栏的实现过程。这个项目可能包含了QTableWidget的分页栏实现,也可能扩展到了QTableView的分页...

    SQL分页语句的三种方法的比较

    对于大型数据集,为了提高用户体验以及减轻服务器负担,通常会采用分页的方式来展示数据。SQL提供了多种实现分页的方法,本文将详细介绍并比较三种常用的SQL分页技术:利用Not In和SELECT TOP分页、利用ID大于多少和...

    C#net各种分页大全

    在ASP.NET中,常见的分页实现方式有以下几种: 1. **控件级分页(Control-level Paging)**:这是最简单的分页实现,通常通过DataGrid、GridView或ListView等数据绑定控件内置的分页功能实现。只需设置控件的Paging...

    几个不错的分页效果--美工效果而已

    标题“几个不错的分页效果--美工效果而已”表明我们将探讨一些具有美观设计的分页实现。描述中的重复内容进一步强调了这个主题,即我们关注的是分页的视觉呈现。 分页效果的设计不仅关乎功能,更在于提升网站的整体...

    Silverlight自定义分页控件

    针对这个主题,博客文章《Silverlight自定义分页控件》提供了详细步骤和源码,作者lijun7788分享了他的实现方式。通过访问给出的链接(http://blog.csdn.net/lijun7788/article/details/8057988),我们可以学习如何...

    几款通用的sql分页存储过程

    ### 几款通用的SQL分页存储过程:深入解析与应用 在数据库操作中,分页查询是一项常见的需求,尤其当数据量庞大时,合理的分页可以极大地提高查询效率和用户体验。本文将深入分析两款通用的SQL分页存储过程,分别...

    java编写的分页操作

    - **Hibernate**:提供Criteria和HQL两种方式,通过`setFirstResult()`和`setMaxResults()`方法实现分页。 - **JPA**:使用`Pageable`接口,通过`PageRequest.of(pageNumber, pageSize)`创建请求对象,传递给`find...

    oracle分页查询sql

    在Oracle数据库中,实现分页查询主要有两种方式:基于`ROWNUM`和基于`OFFSET`和`FETCH`。在早期版本的Oracle中,通常使用`ROWNUM`来实现分页功能。 #### 三、基于ROWNUM的分页查询 基于`ROWNUM`的分页查询是Oracle...

    Mybatis分页拦截器

    Mybatis分页拦截器是Mybatis框架中一种实用的扩展机制,用于实现高效的数据库查询分页功能。在Mybatis中,拦截器扮演着插件的角色,可以监听并修改Mybatis执行过程中的某些行为。本话题将深入探讨Mybatis分页拦截器...

    JAVA分页大全.txt

    下面将详细介绍分页的基本概念、Struts框架中的分页处理方式以及如何使用自定义的`PageController`类来实现分页功能。 ### 分页基本概念 在Web开发中,当数据量较大时,通常不会一次性加载所有数据到页面上,而是...

    ASP分页教程分页教程

    首先,让我们分析提供的代码片段。这段HTML代码展示了一个简单的分页导航条,包含五个链接,分别指向页面1到5。每个链接的`href`属性指定了一个ASP页面(`list.asp`),并传递了一个ID参数(如`id=1120`)。这里的ID...

    java分页代码下载

    在Java Web开发中,通常采用以下几种方式实现分页: 1. **基于SQL查询的分页**:通过SQL语句中的`LIMIT`关键字限制返回的结果集大小。 2. **基于服务器端处理的分页**:在服务器端对数据进行处理,如使用`ArrayList...

Global site tag (gtag.js) - Google Analytics