APP下载

Spring环境下的敏捷ORM框架设计与实现

2019-05-24伍文彬

软件导刊 2019年5期

伍文彬

摘 要:伴随着互联网的发展,各行各业信息化程度不断提升,各种系统应运而生。要提高系统开发效率就必须提高数据库访问层开发效率。通过对多个项目的DAL层进行统计分析,得出通用的CRUD方法集合形成父接口;结合JPA自定义的相关功能注解以及Spring的AOP功能,对Java反射的核心接口InvocationHandler进行JDK的动态代理功能实现;配合基于注解的SQL快速生成并且针对不同数据库模式对LIMIT查询进行逻辑处理,完成分页查询功能,从而完成基于Spring环境开发的快捷ORM实现。系统开发者可根据预定义的注解和相关通用查询方法快捷操作数据库,避免了在Java文件中编写大量的sql文本和xml文件,降低了代码错误率,提高了开发效率。

关键词:Spring;开发效率;数据库;ORM

DOI:10. 11907/rjdk. 191289

中图分类号:TP319 文献标识码:A 文章编号:1672-7800(2019)005-0134-03

Abstract:Along with the development of the Internet, the degree of informatization of all walks of life has also increased, and various systems have emerged. In order to improve the development efficiency of the overall system, it is indispensable to improve the development efficiency of the database access layer. Through statistical analysis of the DAL layer methods of multiple projects, the general CRUD method set is formed into a parent interface; combined with JPA and custom related function annotations and Spring AOP functions, the core interface InvocationHandler is used for Java reflection. The implementation of the dynamic proxy function of the JDK is realised with the rapid generation of annotation-based SQL and the logical processing of the LIMIT query for different database schemas, and the function of paging query is completed to make the implementation of the fast ORM based on the development of the Spring environment. System developers can quickly operate the database according to predefined annotations and related fast general query methods, avoiding to write large quantities of sql strings or xml files in Java files, reducing code error rate and improving development efficiency.

Key Words:Spring; development efficiency; database; ORM

0 引言

ORM(OBJECT RELATIONAL MAPPING)框架,是通过对Java对象的映射表示SQL中的关系模型结构,不必在系统开发中操作SQL语句字符串,只需处理相关Java对象即可对数据库中的数据进行操作[1]。ORM框架为代码操作数据提供了一座桥梁[2],ORM也为开发者解决了面向对象开发时与数据库之间的匹配技术难题[3]。

目前高频率使用的开源ORM框架有JdbcTemplate、MyBatis、Hibernate/JPA等。Hibernate是对jpa规范的实现,提供了强大的对象到关系数据库的持久化服务。开发者无需关心数据库,只需要管理对象状态即可[4],不仅管理数据库表的映射,还提供大量的注解缓存查询功能[5]。MyBatis主要由DAO组件和SQL Map两大组件组成,通过SQL Map与DAO组件之间的映射对数据库进行操作[6],通过SQL Map的xml文件将DAO组件映射为SQL语句,从而实现对数据库的接口式访问。JdbcTemplate则属于Spring下的一个内部封装组件,它将JDBC流程封装起来,包含捕捉异常、执行SQL以及对SQL执行结果的转化等 [8],统一了资源的建立和释放,避免了关闭连接等常见错误[9]。

以上3个框架都是对底层JDBC访问有一定程度的封装,Hibernate提供映射服务数据缓存等功能[10],但在框架中会使用大量注解。MyBatis需要用户书写大量的SQL代码,并且由xml和JAVA代码配合[11]。JdbcTemplate主要对JDBC中的几大组件进行流程化处理[12],三者都需要开发者做额外的维护工作,增加了代码维护的难度。本文实现的ORM框架博采众长,着重于轻量级注解和增删查改(Create、Read、Update、Delete,CRUD)方法的通用性上,對DAL层进行大量通用化和敏捷化处理,弥补了上述方法的不足。

1 框架设计

本文ORM框架名称为template-module-orm,包含通用SQL快速生成模块(template-module-sql)、多模式数据库通用CRUD模块(template-module-jpa)、数据表格分页查询模块(template-module-pagination)以及快速CRUD方法4个模块(template-module-repository),每个模块对应处理不同内容,通过4个模块的合作达到对DAL层的高效开发。

1.1 通用SQL快速生成模块

系统开发需要大量的CRUD操作,尤其select方法占据系统代码量很大一部分。本模块中基于Java实体和表格结构的两种模式,分别实现两种不同系统中常用的CRUD基本语句SQLBeanBuilder和SQLTextBuilder,满足了系统大部分的CRUD,省去了开发者构建基础sql语句的时间。SQLBeanBuilder接口设计包含SQLTextBuilder和SQLBeanBuilder中类似的方法:①生成以count为开头的统计方法sql(包含有无where统计等);②生成以select为开头的查询方法sql(包含where条件选择和查询结果列的选择等);③生成以insert为开头的插入方法sql(包含插入字段的选择以及主键是否参与等);④生成以update为开头的更新方法sql(包含set字段选择和where字段选择等);⑤生成以delete为开头的删除方法sql(包含where的选择和主键参数的选择等)。

1.2 多模式数据库通用CRUD模块

JdbcTemplate是隶属于Spring框架下的一个封装组件。由于JDBC API过于底层,直接进行JDBC操作会很繁琐,因此Spring对其做了初级模板化处理,开发人员只需编写业务代码和SQL语句即可[13],这导致代码中存在大量条件判断语句和SQL语句叠层,增加了代码维护难度。

本模塊针对SQL与Java代码的叠合情况进行分类,实现针对特定类别的sql(如DDL、DML等区别)、特定类型的sql参数(如Map类型、Bean类型、数组类型等)、特定类型的返回结果(如Java基本类型、集合类型、Page类型等)分别进行处理,高效完成数据库操作,同时支持MySQL、SqlServer、Oracle等10种常用数据库。主要接口方法有:①以callProcedure为开头的存储方法(包含对参数和结果的数量和类型的处理);②以insert为开头的插入方法(包含插入参数、返回结果类型和主键的返回与否处理);③以execute为开头的方法(可执行任何insert/update/delete语句的基础方法);④以executeBatch为开头的方法(同上,只不过为批量处理);⑤以findNumber为开头数学查询方法(查询函数结果,包含对参数和结果的类型处理);⑥以findPrimitive为开头的基本类型结果查询方法(返回值预期为Java基本类型);⑦以findList为开头的多列查询方法(查询多列多行,包含参数和结果的类型处理);⑧以findPage为开头的分页查询方法(自动判断数据库类型,生成sql并处理返回结果)。

1.3 数据表格分页查询模块

主要针对后台管理中的表格分页数据进行管理(dataTable)。模块包含3个对象:①Table:主要呈现当前页的数据(List接口的泛型对象数据);②Query:一些页面的信息(页码、页大小、是否支持[多列]排序、排序字段等);③Sorting:排序字段(排序字段、排序方向等)。

将以上3个对象作为参数,根据模块的Pagination处理分页逻辑,Pagination中主要包含如下方法接口:①getPageNo:获取当前页面的页码;②getPageSize:获取当前页面的数据量大小;③getParamsMap:获取查询参数的集合处理结果;④getSql:获取分页查询部分的sql模块(根据不同数据库种类生成不同语句)。

1.4 快速CRUD方法模块

本模块为核心模块,根据用户定义的子接口及方法生成对应的DAL层实例。本模块基于通用CRUD模块实现,子接口必须定义模块中预定义的父接口方可实现快速CRUD功能,父接口如下:①以save开头:处理插入动作,针对不同的参数和主键情况返回预期值和类型;②以delete开头:处理删除方法,根据不同参数和主键返回预期值;③以count/exist开头:根据不同参数处理统计和存在的方法;④以find开头:处理查询select动作;⑤以update开头:根据不同参数和返回类型处理更新操作;⑥除以上之外的用户定义接口方法:根据方法名自动判断执行内容。

2 框架模块实现

2.1 通用SQL模块实现原理

Java反射机制根据一个实例引用解析类的属性和方法,也可新建一个实例[14]。工厂模式可让设计者自行获取产品并规范产品种类,抽象产品,进而保证工厂模式的统一性[15]。合理的单例模式能减少对象的创建次数,减少内存消耗,提高复用性[16]。

本模块根据参数类型,使用工厂类SQLGen生成单例的SQLBeanBuilder或SQLTextBuilder类,之后根据生成的单例类中的方法,通过反射参数中的类名、属性名、方法等关键信息,生成所需要的SQL文本。执行流程如图1所示。

2.2 通用CRUD模块实现原理

基于Spring框架结构,依赖注入(dependency Injection,DI)可为任意的Java对象动态提供所需及生成相对应的实例[17]。

本模块依赖Spring环境下的IOC模式,通过模块中的DaoFactory工厂类实现InitializingBean接口,把工厂类中DataSourceMap提供给Spring进行属性注入,之后通过访问defaultDao等属性访问方法。DaoFactory加载赋值流程如图2所示。

2.3 快速CRUD方法模块实现原理

代理模式尤其是Java的动态代理模式使软件开发人员无须定义代理类,只需指定一组接口及被代理类的对象便可动态获得代理类[18]。Java的动态代理由Proxy类和InvocationHandler接口实现。Proxy类提供了创建动态代理的类及其实例的静态方法[19]。运行过程中Java通过调用动态处理类的bind方法完成被代理类绑定,可无限制地调用被代理类的方法[20]。

本模块依赖Spring环境下基于JDK的动态代理方式,通过RepositoryProxyFactory实现InvocationHandler接口功能,同时使用RepositoryRegistry类BeanDefinitionRegistryPostProcessor接口实现对代理类的注册,实现流程如图3所示。

3 结语

本框架是一个全能的DAL层工具,具有Hibernate/JPA强大的注解功能以及MyBatis易于上手的优点,适用于以SQL为中心同时又要求快速编码的应用。本框架在处理OneToMany(即一对多)表的关系时使用非常顺畅,但在处理ManyToMany(多对多)和ManyToOne(多对一)表的关系时还存在一些疑难问题,这是今后研究改进的重点。

参考文献:

[1] 丁昊志. 对象关系映射模型研究[D]. 北京:华北电力大学,2006.

[2] 梁文菲,黄厚宽. 对象/关系映射技术与面向对象数据库技术比较分析[J]. 中国科技信息, 2006(21):154-156.

[3] AMBLER S W. Mapping objects to relational databases: O/R mapping in detail[EB /OL]. http://www.agiledata.org/essays/mappingObjects.html,2013.

[4] 张少应,程传旭. 基于Hibernate持久化层的设计与实现[J]. 计算机技术与发展,2014(12):101-104.

[5] THE HIBERNATE TEAM,THE JBOSS VISUAL DESIGN TEAM.Hibernate reference document[EB/OL]. http://docs.jboss.org/hibernate/orm/4.3/manual/en-Us/html, 2013.

[6] 徐雯,高建华. 基于Spring MVC及MyBatis的Web应用框架研究[J]. 微型电脑应用,2012(7):1-4.

[7] 王钱,王蓉. 基于ibatis的通用数据持久层的研究与设计[J]. 微计算机信息,2007,23(43):172-174.

[8] 丁振凡,李馨梅. 基于JdbcTemplate的数据库访问处理[J]. 智能计算机与应用,2012(3):29-32.

[9] 刘泉,赵晓明. 基于模板方法的JDBC API的抽象封装与实现[J]. 计算机应用,2006(9):2222-2224.

[10] 汪萌,曲俊华. 基于Hibernate技术的持久层解决方案及实现[J]. 计算机系统应用,2010(3):154-157.

[11] 榮艳冬. 关于Mybatis持久层框架的应用研究[J]. 信息安全与技术,2015(10):86-88.

[12] 张俐,张维玺. 改进的 JDBC 框架在数据持久层的应用[J]. 计算机工程与设计,2010(8):1746-1749.

[13] 赵璘,王红霞. 基于SpringMVC+JDBCTemplate的Web系统的研究与应用[J]. 软件工程,2017(1):5-8.

[14] 温立辉. Java语言反射机制原理探析[J]. 信息系统工程,2016(8):99-100.

[15] 杜增毅. 浅谈主要的 Java 设计模式[J]. 软件应用,2017(8):40-41.

[16] 葛萌,欧阳宏基,陈伟. 单例设计模式的研究与实现[J]. 微型电脑应用,2017(9):68-74.

[17] 王臻,郭芊羽. 基于Spring框架的依赖注入研究[J]. 才智,2014(12):358-359.

[18] 丁民豆. 代理模式的研究与使用[J]. 电脑知识与技术,2011(36):9385-9387.

[19] 卢楠. Java动态代理的研究与应用[J]. 计算机与网络,2014(12):50-52.

[20] 沈凯. 利用反射和动态代理机制实现面向切面的程序设计[J]. 计算机时代,2010(11):56-58.

(责任编辑:杜能钢)