通用分页(上)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS SQL Server,基础系列 2核4GB
简介: 通用分页(上)

                           

                              一通用分页介绍

1.什么是通用分页?

通用分页是一种可以应用于多种数据类型和数据源的分页机制。通常情况下,分页是指从数据库中获取特定数量的记录,并将其按照某种标准划分成一页一页的数据。通用分页可以应用于不同类型的数据集合,如数组、列表、集合等,并且可以支持不同类型的数据源,如数据库、文件、缓存等。

通用分页的主要目的是提高代码的复用性和可维护性,避免在不同情况下重复编写分页逻辑。通用分页通常会定义一个分页参数对象,用于描述分页的基本信息,如每页记录数、当前页码、总记录数等。然后,针对某个具体的数据类型或数据源,可以编写通用的分页逻辑,根据分页参数对象和具体数据源,返回分页结果。

通用分页可以应用于任何需要分页查询的场景,例如Web开发中的分页查询、数据分析中的分页取数、移动端中的分页展示等。通用分页可以帮助我们更快速、更方便地实现分页功能,以及将分页逻辑从具体的业务代码中解耦出来,提高代码的复用性和可维护性。

2.在企业中通用分页的作用

1. 方便复用

企业中的数据处理往往涉及到很多的分页功能,如果每个地方都单独编写分页逻辑,将会增加代码量和维护难度。如果使用通用分页,将分页逻辑抽象出来,封装成通用的分页模块,可以方便复用,减少代码量和维护难度。

2. 提高效率

数据量庞大的企业级应用场景中,通用分页可以通过减少需要处理的数据量,提高查询效率。通过通用分页,可以尽可能地减少数据的读取和传输,从而提高数据库的查询效率,使得企业级应用更加高效。

3. 提高代码可维护性

通用分页机制可以将分页逻辑解耦出来,降低代码的耦合性,提高代码的可维护性。同时,通用分页组件可以更好的处理分页操作中的异常情况,比如页码不合法等,避免代码中出现大量重复的逻辑代码。

4. 提高用户体验

通用分页可以在产品的可用性和易用性方面发挥不小的作用。它可以更好地适应不同的设备和屏幕分辨率,并支持更多的交互方式,例如定制每页显示多少条数据、切换到下一页、上一页、跳转到某一页等,以更好地满足用户的需求,提升用户体验。

3.说明

这是小编自己在学习中分享的一些技术,如果在使用中出现一些问题很抱歉奥!如果有什么问题的话可以私聊小编,小编都会去看的!


                                      二. MySQL,前期准备工作

1.mysql数据库连接

package com.lz.utils;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
 * 提供了一组获得或关闭数据库对象的方法
 * 
 */
public class DBAccess {
  private static String driver;
  private static String url;
  private static String user;
  private static String password;
  static {// 静态块执行一次,加载 驱动一次
    try {
      InputStream is = DBAccess.class
          .getResourceAsStream("config.properties");
      Properties properties = new Properties();
      properties.load(is);
      driver = properties.getProperty("driver");
      url = properties.getProperty("url");
      user = properties.getProperty("user");
      password = properties.getProperty("pwd");
      Class.forName(driver);
    } catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }
  }
  /**
   * 获得数据连接对象
   * 
   * @return
   */
  public static Connection getConnection() {
    try {
      Connection conn = DriverManager.getConnection(url, user, password);
      return conn;
    } catch (SQLException e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }
  }
  public static void close(ResultSet rs) {
    if (null != rs) {
      try {
        rs.close();
      } catch (SQLException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
      }
    }
  }
  public static void close(Statement stmt) {
    if (null != stmt) {
      try {
        stmt.close();
      } catch (SQLException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
      }
    }
  }
  public static void close(Connection conn) {
    if (null != conn) {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
      }
    }
  }
  public static void close(Connection conn, Statement stmt, ResultSet rs) {
    close(rs);
    close(stmt);
    close(conn);
  }
  public static boolean isOracle() {
    return "oracle.jdbc.driver.OracleDriver".equals(driver);
  }
  public static boolean isSQLServer() {
    return "com.microsoft.sqlserver.jdbc.SQLServerDriver".equals(driver);
  }
  public static boolean isMysql() {
    return "com.mysql.cj.jdbc.Driver".equals(driver);
  }
  public static void main(String[] args) {
    Connection conn = DBAccess.getConnection();
    System.out.println(conn);
    DBAccess.close(conn);
    System.out.println("isOracle:" + isOracle());
    System.out.println("isSQLServer:" + isSQLServer());
    System.out.println("isMysql:" + isMysql());
    System.out.println("数据库连接(关闭)成功");
  }
}

注意在实现mysql数据库连接时:要开启mysql服务,就算时自动开启还是要去检查避免数据库启动不了!

1.1.1 数据库连接配置文件

#oracle9i
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:orcl
#user=scott
#pwd=123
#sql2005
#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
#url=jdbc:sqlserver://localhost:1433;DatabaseName=test1
#user=sa
#pwd=123
#sql2000
#driver=com.microsoft.jdbc.sqlserver.SQLServerDriver
#url=jdbc:microsoft:sqlserver://localhost:1433;databaseName=unit6DB
#user=sa
#pwd=888888
#mysql
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_ssm?useUnicode=true&characterEncoding=UTF-8&useSSL=false
user=root
pwd=123456

注意:这个文件和数据库连接在同一个包里,并且在使用这两个文件使用连接数据库时可以1根据自己的需求来进行不同的数据库连接,在这里我连接的是MySQL,

1.1.2 实体类

注意:在创建实体时要注意是否和数据库的类型,名字一致,不然在后续的操作中会影响,还可能产生一些错误

package com.lz.entity;
public class Book {
  private int bid;
  private String bname;
  private float price;
  @Override
  public String toString() {
    return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + "]";
  }
  public int getBid() {
    return bid;
  }
  public void setBid(int bid) {
    this.bid = bid;
  }
  public String getBname() {
    return bname;
  }
  public void setBname(String bname) {
    this.bname = bname;
  }
  public float getPrice() {
    return price;
  }
  public void setPrice(float price) {
    this.price = price;
  }
}

2.过滤器

作用:解决中文乱码,以及编码的不同从而进行筛选

package com.lz.utils;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 中文乱码处理
 * 
 */
public class EncodingFiter implements Filter {
  private String encoding = "UTF-8";// 默认字符集
  public EncodingFiter() {
    super();
  }
  public void destroy() {
  }
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    // 中文处理必须放到 chain.doFilter(request, response)方法前面
    res.setContentType("text/html;charset=" + this.encoding);
    if (req.getMethod().equalsIgnoreCase("post")) {
      req.setCharacterEncoding(this.encoding);
    } else {
      Map map = req.getParameterMap();// 保存所有参数名=参数值(数组)的Map集合
      Set set = map.keySet();// 取出所有参数名
      Iterator it = set.iterator();
      while (it.hasNext()) {
        String name = (String) it.next();
        String[] values = (String[]) map.get(name);// 取出参数值[注:参数值为一个数组]
        for (int i = 0; i < values.length; i++) {
          values[i] = new String(values[i].getBytes("ISO-8859-1"),
              this.encoding);
        }
      }
    }
    chain.doFilter(request, response);
  }
  public void init(FilterConfig filterConfig) throws ServletException {
    String s = filterConfig.getInitParameter("encoding");// 读取web.xml文件中配置的字符集
    if (null != s && !s.trim().equals("")) {
      this.encoding = s.trim();
    }
  }
}

3.分页代码前期准备

当前页:page

显示记录数:rows

总记录数:total

start =(page-1)*rows

是否分页:pagination

根据需求来判断

package com.lz.utils;
/**
 * 分页工具类
 *
 */
public class PageBean {
  private int page = 1;// 页码
  private int rows = 10;// 页大小
  private int total = 0;// 总记录数
  private boolean pagination = true;// 是否分页
  public PageBean() {
    super();
  }
  public int getPage() {
    return page;
  }
  public void setPage(int page) {
    this.page = page;
  }
  public int getRows() {
    return rows;
  }
  public void setRows(int rows) {
    this.rows = rows;
  }
  public int getTotal() {
    return total;
  }
  public void setTotal(int total) {
    this.total = total;
  }
  public void setTotal(String total) {
    this.total = Integer.parseInt(total);
  }
  public boolean isPagination() {
    return pagination;
  }
  public void setPagination(boolean pagination) {
    this.pagination = pagination;
  }
  /**
   * 获得起始记录的下标
   * 
   * @return
   */
  public int getStartIndex() {
    return (this.page - 1) * this.rows;
  }
  @Override
  public String toString() {
    return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
  }
}

                         三.老版Dao和新版Dao

1.老版普通Dao

* 
  public List<Book> list(Book bk, PageBean pageBean) throws Exception {
    List<Book> list = new ArrayList<Book>();
    Connection conn = DBAccess.getConnection();
    String sql = "select  *from  t_mvc_book  where  1=1";
    String bname = bk.getBname();
    if (StringUtils.isNotBlank(bname)) {
      sql += "  and  bname like '%" + bname + "%'  ";
    }
    PreparedStatement ps = conn.prepareStatement(sql);
    ResultSet rs = ps.executeQuery(sql);
    while (rs.next()) {
      Book b = new Book();
      b.setBid(rs.getInt("bid"));
      b.setBname(rs.getString("bname"));
      b.setPrice(rs.getFloat("price"));
      list.add(b);
    }return list;
  }

2.通用查询Dao

2.1创建BaseDao

package com.lz.utils;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class BaseDao<T> {
  public List<T> executeQuery(String sql, Class clz, PageBean pageBean) throws Exception {
    List<T> list = new ArrayList<T>();
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    if (pageBean != null && pageBean.isPagination()) {
      String countSql = getCountSql(sql);
      conn = DBAccess.getConnection();
      ps = conn.prepareStatement(countSql);
      rs = ps.executeQuery(countSql);
      if (rs.next()) {
        pageBean.setTotal(rs.getObject("n").toString());
      }
      String pageSql = getPageSql(sql, pageBean);
      conn = DBAccess.getConnection();
      ps = conn.prepareStatement(pageSql );
      rs = ps.executeQuery(pageSql );
    } else {
      conn = DBAccess.getConnection();
      ps = conn.prepareStatement(sql);
      rs = ps.executeQuery(sql);
    }
    while (rs.next()) {
      // 通过泛型来代替 Book b = new Book();
      T t = (T) clz.newInstance();
      Field[] fields = clz.getDeclaredFields();
      for (Field f : fields) {
        f.setAccessible(true);
        // System.out.println(f.getName());
        f.set(t, rs.getObject(f.getName()));
        list.add(t);
      }
    }
    return list;
  }
  /**
   * sql bookdao的sql 最终sql
   * 
   * @param sql
   * @param pageBean
   * @return
   */
  private String getPageSql(String sql, PageBean pageBean) {
    return sql + "  LIMIT  " + pageBean.getStartIndex() + "," + pageBean.getRows();
  }
  /**
   * 查询 总记录数
   * 
   * @param sql
   * @return
   */
  private String getCountSql(String sql) {
    return "SELECT  COUNT(1)  as  n  from (" + sql + ")  t ";
  }
}

2.2通用查询Dao

public List<Book> list(Book bk, PageBean pageBean) throws Exception {
    String sql = "select  *from  t_mvc_book  where  1=1";
    String bname = bk.getBname();
    if (StringUtils.isNotBlank(bname)) {
      sql += "  and  bname like '%" + bname + "%'  ";
    }
    return super.executeQuery(sql, Book.class, pageBean);
  }

3.二者区别

新版本:在就版本的基础上将

      代码重复

       Connection conn = DBAccess.getConnection();

       PreparedStatement ps = conn.prepareStatement(sql);

       ResultSet rs = ps.executeQuery(sql);

       流程重复

       1.创建表相对应的实体对象

       2.查询 的结果天加到实例化对象属性中

       3被添加的实体对象,加入集合中

       while (rs.next()) {

           Book b = new Book();

           b.setBid(rs.getInt("bid"));

           b.setBname(rs.getString("bname"));

           b.setPrice(rs.getFloat("price"));

           list.add(b);

       }

通过使用basedao将其封装起来,在使用泛型,反射来调用实体,来替换while包裹的那一段代码

hile (rs.next()) {

           // 通过泛型来代替 Book b = new Book();

           T t = (T) clz.newInstance();

           Field[] fields = clz.getDeclaredFields();

           for (Field f : fields) {

               f.setAccessible(true);

               // System.out.println(f.getName());

               f.set(t, rs.getObject(f.getName()));

               list.add(t);

           }

最后通过将那些重复的代码,过程进行合并,从而减少代码量


                           四.Juint使用

1.为什么要使用.Juint

以下是使用JUnit的好处:

1. 自动化测试

使用JUnit自动化测试的好处是可以节省大量的时间和精力,同时可以保证测试正常,减少手工测试产生的错误和疏漏。

2. 易于维护

使用JUnit测试代码可以使代码更易于维护。单元测试代码类似于使用注释和文档,为代码提供说明和提示。因此,单元测试代码使得代码更易于理解和修改,减少引入潜在错误的风险。

3. 及时反馈

使用JUnit测试代码可以及时反馈代码更改可能带来的影响和错误,这样有利于在代码构建周期早期发现并修复问题。JUnit测试框架总是能够迅速地指出程序的问题所在,这其中可以包括难以重现的问题、处理边角情况的错误以及健壮性方面的缺陷。

4. 持续集成

JUnit在持续集成流程中发挥了很大的作用。持续集成是一种软件开发流程,在这个过程中,会自动化执行不同的测试,因此,JUnit是持续集成流程的重要组成部分。

5. 可靠性和稳定性

代码的质量和可靠性至关重要,JUnit可以帮助我们验证自己的代码功能,并使其具有更高的可靠性和稳定性。始终检查和验证代码的行为,可确保开发人员不会疏忽或忽略任何关键的或边缘情况,提供了一种稳定和可靠的实现方式。

2.在企业中.Juint有什么用

在企业中,JUnit具有以下用途:

1. 保证代码质量

在企业级应用中,代码的质量至关重要。JUnit提供了一种简单、快速、可重复的方式来检查代码的行为和逻辑。通过运行自动化的JUnit测试套件,企业可以确保代码始终具有良好的质量。

2. 检查代码更改

在企业中,任何一次代码更改都有可能引入新的错误或破坏代码的功能性。JUnit自动化测试可以检测出这些错误并及时修复,这有助于保持代码的稳定性和质量。

3. 方便持续集成

在企业中,持续集成是一种流行的开发方式。JUnit测试套件可以与持续集成工具集成,例如Jenkins,以确保每次提交都会运行测试,并在出现错误时立即发布警告。

4. 提高代码可维护性

在企业中的长期运维中,代码必须具有良好的可维护性。JUnit测试使得代码更容易理解和维护,因为它可以提示代码的问题所在,从而更容易识别和修复代码的缺陷。

5. 降低错误和缺陷

JUnit是一种强大的测试工具,在应用中广泛使用。使用JUnit测试你的代码可以降低新错误的出现几率,通过检测错误,他可以帮助测试人员或开发人员更加容易地了解错误的来源和出现方式,从而提高代码质量和产品可靠性。

3.使用操作

1.选择项目,build path然后直接点下去

2.点击右侧的  add libary

3.选择,Junit ,next,finish

4输出@Test 就可以

为什么要使用?

可以同时测试多个方法,节省效率

@Test
  public  void text1 () throws Exception {
    System.out.println("text1来了");
    BookDao bookDao = new BookDao();
    Book book = new Book();
      book.setBname("圣墟");
    PageBean pageBean = new PageBean();
    List<Book> list = bookDao.list(book, pageBean);
    for (Book b : list) {
      System.out.println(b);
    }
  }
  @Test
  public  void text2 () throws Exception {
    System.out.println("text2来了");
    BookDao bookDao = new BookDao();
    Book book = new Book();
      book.setBname("圣墟");
    PageBean pageBean = new PageBean();
    List<Book> list = bookDao.list(book, pageBean);
    for (Book b : list) {
      System.out.println(b);
    }
  }

             


                          五.分页实际效果实现

1.sql语句编写

1.1在最开始的sql语句

public List<Book> list(Book bk, PageBean pageBean) throws Exception {
    String sql = "select  *from  t_mvc_book  where  1=1";
    String bname = bk.getBname();
    if (StringUtils.isNotBlank(bname)) {
      sql += "  and  bname like '%" + bname + "%'  ";
    }
    return super.executeQuery(sql, Book.class, pageBean);
  }

1.2拼接的sql语句

在basedao封装的通用查询的基础上进行拼接,然后在进行重现方法。

在进行拼接时判断是否需要拼接,和条数

public List<T> executeQuery(String sql, Class clz, PageBean pageBean) throws Exception {
    List<T> list = new ArrayList<T>();
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    if (pageBean != null && pageBean.isPagination()) {
      String countSql = getCountSql(sql);
      conn = DBAccess.getConnection();
      ps = conn.prepareStatement(countSql);
      rs = ps.executeQuery(countSql);
      if (rs.next()) {
        pageBean.setTotal(rs.getObject("n").toString());
      }
      String pageSql = getPageSql(sql, pageBean);
      conn = DBAccess.getConnection();
      ps = conn.prepareStatement(pageSql);
      rs = ps.executeQuery(pageSql);
    } else {
      conn = DBAccess.getConnection();
      ps = conn.prepareStatement(sql);
      rs = ps.executeQuery(sql);
    }
    while (rs.next()) {
      // 通过泛型来代替 Book b = new Book();
      T t = (T) clz.newInstance();
      Field[] fields = clz.getDeclaredFields();
      for (Field f : fields) {
        f.setAccessible(true);
        // System.out.println(f.getName());
        f.set(t, rs.getObject(f.getName()));
        list.add(t);
      }
    }
    return list;
  }
/**
   * sql bookdao的sql 最终sql
   * 
   * @param sql
   * @param pageBean
   * @return
   */
  private String getPageSql(String sql, PageBean pageBean) {
    return sql + "  LIMIT  " + pageBean.getStartIndex() + "," + pageBean.getRows();
  }
  /**
   * 查询 总记录数
   * 
   * @param sql
   * @return
   */
  private String getCountSql(String sql) {
    return "SELECT  COUNT(1)  as  n  from (" + sql + ")  t ";
  }

1.3得到完整的效果

public List<Book> list(Book bk, PageBean pageBean) throws Exception {
    String sql = "select  *from  t_mvc_book  where  1=1";
    String bname = bk.getBname();
    if (StringUtils.isNotBlank(bname)) {
      sql += "  and  bname like '%" + bname + "%'  ";
    }
    return super.executeQuery(sql, Book.class, pageBean);
  }

2.MySQL中 limit使用

limit(0,10)  作用: 其始下标  ,显示页数

SELECT  *FROM  t_mvc_book  WHERE  bname LIKE 
'%圣墟%'  LIMIT  0,10
SELECT  *FROM  t_mvc_book  WHERE  bname LIKE 
'%圣墟%'  LIMIT  10,10

 

3.所有你学废了嘛?

 

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
前端开发 Java 测试技术
通用分页【上】
JUnit是流行的、开源的Java单元测试框架,它提供了一种简单而强大的方式来测试Java应用程序中的单元代码。JUnit测试通常涉及创建和运行测试用例,而测试用例是一组独立的测试步骤,用于验证代码是否按照预期工作。JUnit测试通常分为以下四个步骤:定义测试用例:定义每个测试方法所需的输入参数以及期望的输出结果;编写测试代码:编写测试方法并使用断言(Assertion)来验证代码是否按照预期工作;运行测试用例:通常使用JUnit测试浏览器或者其他测试工具来运行测试用例;查看测试结果。
|
SQL 前端开发 Java
通用分页-后台
通用分页-后台
97 0
|
前端开发 数据管理 Java
通用分页(下)
通用分页(下)
61 0
|
算法 JavaScript Java
通用分页【下】(将分页封装成标签)
调试()是指在软件开发过程中,通过识别、定位和解决程序错误或问题的过程。调试的目的是找出代码中的错误、异常或不正常的行为,并修复它们,以确保程序能够按照预期的方式运行。调试是一个重要的开发技巧,可以帮助开发人员理解程序的执行过程、找出错误的原因,并从中学习和改进。调试可以使用不同的工具和技术来辅助,例如打印输出、日志记录、调试器(debugger)等。调试是开发过程中不可或缺的一部分,可以帮助开发人员提高代码质量、加快解决问题的速度,并优化程序的性能和可靠性。
dapper通用分页方法
dapper通用分页方法
180 0
|
Java 数据库
通用分页之详解】
通用分页之详解】
54 1
|
监控 前端开发 算法
通用分页(前端)
通用分页(前端)
55 1
|
10月前
|
前端开发 关系型数据库 MySQL
通用分页详解
通用分页详解
73 0
通用分页(后台分页)
通用分页(后台分页)
69 0
|
前端开发
通用分页02(前台分页)
通用分页02(前台分页)
67 0