一种支持多条件过滤查询的分页组件设计与实现

时间:2022-09-20 04:48:26

一种支持多条件过滤查询的分页组件设计与实现

摘要:常见的分页组件存在一些不足,针对多条件组合过滤的分页查询业务场景提出了改进方案,在实现分页查询封装的同时给业务开发者提供足够的开发灵活性,并在Spring MVC开发框架的基础上实现了该分页组件,在视图层使用JQuery实现了一个与后台开发框架完全分离的分页页面组件,在后台使用泛型和桥接模式实现了分页查询的封装。应用结果表明该组件能够满足日常开发中的所有应用场景,且具有较好的移植性和稳定性。

关键词:分页组件;查询优化;分页框架;Spring框架

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2014)03-0514-06

在企业级应用开发中,对业务实体信息的多条件组合过滤查询是基本功能之一。针对客户的查询要求,服务器可以一次性将符合条件的所有数据推送给客户端,但这种方式只适合返回少量数据集的情况。针对大型和超大型数据集,服务器必须采用分页的方式将符合要求的数据以分页的方式推送给客户端。文献[1]提出了一种基于MVC的分页组件,但对应的查询语句写死在分页抽象类中,这就导致了该分页组件没办法满足多条件组合过滤查询和对结果集按照特定属性进行排序等应用场景。文献[2]使用泛型DAO实现了支持多条件组合查询和对结果集进行排序的分页组件,但是实现方法是将查询过滤条件和排序字段以键值对的方式存放在Map中,这就要求业务开发者在处理分页查询时需要进行二次加工,将过滤条件或者排序条件按照预定好的方式组成键值对推入到预定义好的Map变量中,这种方式将界面查询元素和分页查询处理代码进行了紧耦合,不但增加了程序调试和维护的难度,且增加了业务开发者的工作量。另外上述两种方法也都是针对单个对象的分页查询应用,对多个对象间关联查询的应用场景支持不了,而在实际企业应用中,这种多表关联查询的分页查询业务场景非常多,且分页的多个查询条件通常是动态组合的。在多条件动态组合查询业务场景中,对于有N个查询条件,这N个查询条件的不同拼接顺序得到的不同JPQL或者SQL语句在执行效率方面相差非常大[3-5],因此在数据查询业务中需要给业务开发人员提供足够的开发灵活性,让其在拼接查询语句时可以根据数据库表的设计、数据量和对应SQL优化器的工作原理对查询条件进行拼接,取得最优的执行效率。

针对上述问题,本文提出了一种改进的Web分页组件方法,在实现分页查询封装的同时给业务开发者提供足够的开发灵活性,在满足分页组件的可扩展性和可移植性要求的同时,达到提高代码可维护性、增加业务开发者的开发灵活性和提高最终应用软件的执行效率等目的。

1 相关实现技术

1.1 Spring MVC

Spring框架提供了构建Web应用程序的全功能MVC模块 ,是一种高度可配置的MVC框架,可以定制本地化和主题解析,并提供多种视图技术,实现了控制器、模型对象、分派器以及处理程序对象的多角色分离,这种分离让它们更容易进行定制,在视图层,Spring提供了视图解析器使其可以在浏览器中直接显示模型数据 [6-7]。

1.2 Java泛型

泛型是程序设计语言的一种特性,允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,对于这些可变部分允许在其使用前再声明具体的类型,Java泛型是Java SE 1.5及以上版本的新特性。在Java编程中,常常用到在容器中存放对象或从容器中取出对象,并根据实际情况转型为相应的对象,但在转型过程中极易出现错误,且很难发现。而使用泛型则可以在存取对象时明确指名对象的类型,将问题暴露在编译阶段,由编译器检测,从而避免Java在运行时出现转型异常,增加程序的可读性与稳定性,提高程序的运行效率[1]。

1.3 JPA

JPA(Java Persistence API)通过注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。由于传统的O/R 映射解决方案太多,不方便开发人员的学习和使用,JPA则提供了数据访问的统一规范和标准[1]。JPA包括以下优势:1)标准化;2) 简单易用,集成方便;3) 可媲美JDBC 的查询能力。

1.4 JQuery

JQuery是一个轻量级的JavaScript脚本,支持cssl、css2、css3定义的属性和选择器,兼容多种浏览器。开发人员除了可以使用JQuery自身带有的显示和隐藏元素特效外,还可以通过插件实现更多功能,如表单验证、Tab导航、拖放效果、表格排序、树形菜单、图像特效以及Ajax上传等,极大地方便了开发人员快速开发动态效果网页。

2 分页组件业务架构设计

当前大部分web应用都采用了MVC架构模式,该模式把软件系统分为模型(Mode1)、视图(View)和控制器(Controller) 3个部分,其中Model对象包含数据,View对象负责显示有模型包含的数据,用于与用户交互,Controller对象是介于Model与View之间的桥梁,它可以分发和处理用户的请求,选择适当的视图用于显示模型包含的数据返回给用户[8]。因此分页组件需要灵活适应这种开发架构模式,为业务开发者提供一个既能满足各种业务需求的分页组件,提高程序开发者的工作效率和开发灵活性,同时也能够提高整个软件的代码可读性和扩展性。与MVC架构模式对应,分页组件的整体业务架构设计图也分为视图层、控制器层和模型层,具体如图1所示。在视图层,分页组件提供了一个可以随意嵌入的分页页面组件,该页面负责分页信息的展示、分页功能(比如上一页、下一页等)的触发事件监听和分页信息的传递;在模型层,提供记录分页信息和结果集数据的Page对象;在控制器层,为了给业务开发者提供足够的开发灵活性,业务开发者只需要实现分页接口并实现对应的分页查询方法即可,具体分页查询业务代码则可以根据实际的业务逻辑和数据库设计灵活定制。

整个分页处理过程可以分为如下四个步骤:

1) 用户通过业务展现页面向Web服务器发出各种查询条件和分页信息,分页信息具体包括当前页数、每页显示记录数等信息。

2) 业务逻辑层相应方法接收查询条件对象和Page对象,然后调用数据层对应DAO的分页查询方法。

3) 数据层的分页查询方法根据查询条件对象里面的查询条件,动态组装查询条件,然后调用数据访问方法,获取结果数据后将整个数据集的情况和满足条件的结果记录集存储到Page对象中,并返回给业务逻辑层;业务开发人员在分页查询方法中可以根据实际业务情况和数据库设计自由定制查询语句。

4) 视图层根据Page对象数据结构访问对应的数据成员,分别展现业务数据和分页数据,其中视图层由业务展现页面和分页页面组件组成,业务展现页面负责展现符合条件的业务数据记录集,分页页面组件负责展现分页信息。

3 分页组件实现

3.1 完全分离的分页页面组件实现

为了实现分页页面的直接复用,一般分页页面都是以一个独立的页面组件嵌入到需要分页的主页中,但分页功能需要与后台服务进行数据交换,因此大部分实现方案都是通过在分页页面组件中使用自定义的标签或者第三方开源框架标签,如Struts标签等[9]。这种实现方式一定程度上限制了分页页面组件的移植,一旦后台使用的第三方开源框架发生变化,则分页页面组件使用的标签库也需要随之改变。为了实现与后台第三方开发框架完全分离的分页页面组件,本文在分页页面组件中采用了纯JS来实现分页页面组件与后台的数据交换功能,具体的JS实现则采用JQuery来实现。首先在分页页面组件加载时,针对页面上的每个按钮注册对应的监听事件,当对应的按钮发生事件时,则触发对应的监听功能方法,在功能方法中则通过以下几步来完成与后台的服务器请求:获取页面输入项的值、检验输入值的合法性、截取嵌入主页的服务地址、组装分页信息page对象、动态设置嵌入主页面的后台服务地址和触发业务展现页面的查询按钮向服务器发起数据请求,具体的分页页面组件处理流程图如图2所示。

页面组件的使用方式与其他分页组件使用方法相似,业务展现页面只需要通过方法将分页页面组件page.jsp包含进去即可,不需要另外再添加任何其他代码。

3.2 传递分页信息的Page类定义及描述

Page对象负责将用户设置的分页信息通过Action传递给数据查询Dao,以及将查询后的结果传递给页面,基于泛型进行Page对象进行设计,定义为public class Page,类的实现主要包括四部分:

1) 分页信息私有成员,包括待分页显示记录总数totalRows、默认每页显示的记录数pageSize,当前页页码currentPage、记录集的总页数、开始行数startRow;

2) 符合要求的分页数据集私有成员,用于存储符合查询条件的当前页面显示具体内容,定义为private List list;

3) 构造函数,需要往构造函数传递总记录行数和每行显示的记录数(可选),构造函数根据传递进来的值设置记录总数、计算偏移量、实际显示记录数以及页码值校正;

4) 私有成员的getter和setter方法,针对1) 和2) 中的私有成员,形成其getter和setter方法。

根据以上设计,Page类的主要实现代码如下所示:

public class Pager {

private int totalRows;//总行数

private int pageSize = 15;//页面行数

private int currentPage;//当前页

private int totalPages;//总页数

private int startRow;//开始行

private List list;//当前页数据

public Pager(int _totalRows,int _pageSize) {

pageSize = _pageSize;

totalRows = _totalRows;

totalPages = totalRows / pageSize;

int mod = totalRows % pageSize;

if (mod > 0) {

totalPages++;

}

currentPage = 1;

startRow = 0;

}

… … //不含_pageSize的构造函数

… … //成员变量的getter和setter方法

}

3.3 分页查询处理业务逻辑

分页查询一般都是在一个较大的数据集上做查询,并根据一个或者多个条件对数据集过滤进行精确查询,而对于不同的数据库表结构和索引字段,过滤条件组合的先后顺序和多表连接查询时表连接的顺序对查询效率影响较大,因此分页查询在实现封装的同时还需要给业务开发者一定的灵活性,以达到分页查询的执行效率最优化。文献[8]使用“IDAO+DAO”的实现模式对分页查询进行了封装,该方式较好的将DAO的实现部分与使用它的Action进行了分离,但是它将查询字段信息和数据库表信息通过字符串的方式从页面一直传递到DAO,对DAO和页面进行了紧耦合,不利于程序的扩展和理解;文献[2] 采用“泛型+反射+桥梁”模式对分页查询封装进行了改进,但是它将查询语句封装到开发人员不能修改的GerneticDAO中, 导致该模式不能支持多表连接查询和多条件组合查询的业务需求。在前人研究的基础上,本文也采用了“泛型+反射+桥梁”模式对分页查询进行封装,但与文献[2]的区别是就是将分页查询语句的动态组装留给业务开发者自己,开发者可以根据实际的业务情况对分页查询进行优化,具体如图3所示。

1) 为了实现分页查询功能的封装,定义一个接口IDao,里面包含一个基于泛型的分页方法,具体如下所示:

public interface IDAO {

public Page getListDataOnPage(Class queryObject, Page pager,dao:IDAO);

}

2) 所有需要用到分页功能的DAO都继承这个接口,必须实现getListDataOnPage方法,但在getListDataOnPage方法中,业务开发人员需要根据实际业务、表结构及索引自己组装查询语句,然后使用JPA集合分页功能,使用setFirstResult 方法设置结果集中第一个结果的位置和使用setMaxResults 方法获得最大实体数量,这就给业务开发者提供了足够的灵活性,为高性能应用程序的开发实现提供了基础。

3) 为了实现页面上的多条件查询与查询DAO之间的解耦,所有的查询过滤条件都是通过queryObject对象进行传递的,queryObject可以是对应返回对象的实体,也可以是一个新的POJO实体。业务开发人员根据queryObject对象中的过滤条件自由组装查询条件,具有多个组合查询条件的动态组合业务流程图如图4所示。

在“根据查询对象的值拼装查询SQL”这个过程中,业务开发者需要根据业务系统的数据结果和数据库SQL优化器工作原理对查询条件的拼接先后顺序进行优化,从而获得性能最优的分页查询语句,比如针对ORACLE数据库,能够过滤最大数量记录的条件应该拼接在WHERE子句的末尾等。

4 应用效果分析

分页组件是软件架构师提供给业务开发者编程使用的一个组件,可以使用软件产品质量标准来评价该组件,国际标准化组织第一联合技术委员会和国际电工技术委员会出版了一系列软件产品质量标准,如著名的ISO/IEC 9126[10,11], 根据常见的软件质量属性对本文提出的分页组件分析具体如下所示。

1)在展现层提供一个页面组件给业务开发者直接嵌入使用,在控制层通过开发取数接口让业务开发者自己根据实际业务动态组装查询数据语句,增加了业务代码编写的灵活性,降低了该组件的使用难度,使得该组件具有良好的易用性。

2)在分页处理过程中将分页业务、查询条件和分页信息都封装成对象,在数据查询Dao层通过使用JPA技术屏蔽各个数据库的差异,使得该组件具有良好的可扩展性和可维护性。

3)该分页组件由一个完全分离的分页页面组件和使用接口与Java Bean技术编写的分处理页后台组成,使其可以在任何J2EE开发框架中使用,具体良好的移植性。

5 结论

针对Web业务系统的多条件组合过滤的分页查询问题,在其他研究者的基础上实现了一种支持多条件组合查询的改进分页组件模型,该模型在实现查询封装的同时,又给业务开发者提供了足够的开发灵活性,可以满足多条件过滤和多表查询等各种业务情况。该分页组件已在多个软件中使用,对应的软件也已部署到多个电信公司使用,对于千万级记录集的分页查询也能够取得非常好的性能,获得较好的客户评价。

参考文献:

[1] 孟晨,赵春亮,张建国.泛型DAO模式在Java Web开发中的应用[J].计算机应用与软件,2012,29(1):l75-l77.

[2] 张俐.基于MVC模式的分页组件应用[J].计算机工程,2011,37(21):255-257.

[3] 李 辉,王瑞波.多条件分页查询优化的设计方法[J].计算机工程,2010,36(2):51-52.

[4] Pentaris E,Ioannidis E.Query Optimization in Distribute Networks of Autonomous Database Systems[J].ACM Transactions on Database Systems,2006,31(2):538-538.

[5] 金洪伟,苏厚勤.查询表达式优化的研究与实现[J].计算机应用与软件,2008,25(6):123-125.

[6] 薛峰,梁锋,徐书勋,等.基于 Spring MVC 框架的 Web 研究与应用[J].合肥工业大学学报:自然科学版,2012, 35(3): 337-340.

[7] 张宇,王映辉,张翔南.基于Spring的MVC框架设计与实现[J].计算机工程,2010,36(4):59-62.

[8] 张俐. MVC 模式在数据中间件中的应用[J].计算机工程,2010,36(9): 70-72.

[9] 何玲娟,蚁龙,刘连臣.一种松耦合高复用MVC 模式的Web分页实现[J].计算机工程与应用,2007,43(15): 95-97.

[10] ISO/IEC JTCl/SC7.Software engineering-Product quality-Quality Model[S]. ISO 2001.

[11] ISO/IEC JTCl/SC7.Software engineering-Product quality-External quality metrics[S].2003.

上一篇:基于数据挖掘的英语四级成绩分析与预测 下一篇:UML模型测试的研究综述