标题 | 一种基于源码分析和代码生成的ORM开发工具 |
范文 | 瞿华 摘要:目前在开发信息系统时,数据持久化功能多采用ORM(对象——关系映射)框架,如Hiberate、MyBatis来进行。这类框架降低了数据持久化功能开发工作量,提升了软件开发和维护的效率,但同时也降低了系统的运行速度、消耗了更多的内存等资源。针对现有ORM框架运行效率低的缺点,该文提出了一种在代码开发阶段使用源码分析获取ORM元信息,自动生成相关代码的数据持久化功能开发方法,并以Intelli IDEA平台插件的形式设计和开发了相应的工具——EasyPersist 。本文通过实验程序,将自动生成的持久化代码与使用Hibernate框架的代码进行了对比实验,证明了所提出的方法的有效性。 关键词:数据持久化;ORM;源码分析;代码生成 中图分类号:TP317 文献标识码:A 文章编号:1009-3044(2016)20-0083-04 1 背景 黑龙江省森林工业总局(龙江森工)是我国最大的国有林区和森林工业集团。龙江森工为了提升自身的管理水平,委托笔者所在的课题组开发和实施智慧林业信息管理平台项目。笔者在项目的调研过程中了解到,基层职工多,包袱重,人均收入低,信息化投入有限,是影响国有林业企业基层信息管理系统普及的重要因素。因此,尽可能地提高信息系统的运行效率,降低系统对运行环境的要求,减少系统运维成本,对于在林业部门普及和推广信息系统具有重要的意义。 为了应对问题领域的复杂性,较好地适应需求的变化,目前的信息系统大多采用面向对象方法进行开发,用实体对象[1]来组织和表示系统在运行过程中获取和产生的各种信息。而与此同时,在信息的持久化存储上,大多数信息系统还在采用传统的关系式数据库,即使用关系数据表来存储信息。因此,在大多数信息系统中,都必须通过某种方式来实现从对象和关系式数据的转换,即所谓的对象——关系映射(Object-Relational Mapping,简称ORM)功能[2-4]。 目前有多种ORM框架,如Hiberante[5]、iBatis[6]等,可以帮助开发者简化ORM功能的开发。这些ORM框架都是在程序运行时,通过反射来动态访问实体对象的属性和方法[7, 8],不需要对象实现特殊的接口或方法,具有较高的灵活性,易于部署和使用,因此得到了广泛的应用。 但这些ORM框架也存在一些天然的缺陷,如:1)必须使用反射机制动态访问实体对象,增加了系统运行时的开销,降低了系统的运行效率;2)数据库操作完全在程序运行时动态生成,开发人员难以控制和优化[9-12]等。 针对传统ORM框架运行效率较低的缺点,本文提出了一种新的在代码开发阶段,自动生成源代码的ORM开发方法,并在Intellij IDEA平台①上设计和实现了相应的ORM开发工具——EasyPersist②。使用该工具,可以自动生成实体类的ORM持久化代码。生成的代码可供开发人员利用继承或嵌入等方式直接使用,也可以自由的进行修改和优化。因此本方法在未牺牲开发效率的前提下,为开发人员提供了更大的灵活性。此外,由于没有运行时的反射等开销,最终程序的代码运行效率也更高。该工具在实际项目《龙江森工集团智慧决策平台》的开发中得到了应用,取得了较好的效果。 2 问题描述 2.1 ORM功能 在使用面向对象方法开发的系统中,实体对象(Entity)是数据的基本组织和存储单位,数据多以实体对象属性的形式存在。当系统需要将实体对象中的数据持久化保存到数据库中时,必须将实体对象的属性值转化成对应的数据记录的字段参数;同样的,当系统需要从数据库中载入数据时,也必须将数据库返回的查询结果中的字段数据转化为对应的实体对象属性,如表1所示。这就是所谓的ORM功能。 由于ORM本质上是对数据库访问接口的机械调用和数据格式之间的转换,因此可以用某种自动化工具来对其进行封装,从而简化系统的开发。根据这一思想,产生了ORM框架。使用ORM框架开发的系统,无须编写数据库访问和数据映射转换代码,只需要将转换信息(ORM元信息)提供给ORM框架,然后调用相关的API即可。除此之外,很多ORM框架还提供了实体间关系映射的处理、缓存等高级功能。 但这些框架都需要在系统运行时,动态生成SQL查询语句,并通过反射等方式动态创建和访问实体对象,因此需要额外消耗一定的内存和CPU等资源,与手工编写的ORM相比,运行效率较低;此外,由于SQL语句在运行时动态生成,难以对其进行手动优化,因此这类框架也普遍存在着复杂查询效率低的问题。 2.2 ORM元数据与注解 ORM主要是实体对象(属性)和关系数据(字段)之间的转换,不管哪种ORM工具,都需要知道实体和数据表、属性和字段等之间的对应关系,才能完成转换。这些对应信息就构成了所谓的ORM元信息(meta information)。目前,主要有三种方法来提供ORM元信息,即约定[13]、XML映射文件和注解[14, 15]。 约定方式是指程序开发者按照预先约定好的规则来命名相关的程序和数据库元素,如要求实体类和数据表的名称必须相同等。这种方法工作量较小,但灵活性和兼容性差,主要用在各种快速开发框架中;XML映射文件方式是指以XML格式的配置文件提供相关的ORM元信息,使用较为灵活,但配置信息和程序代码分离也带来了一些开发维护上的问题;注解方式是通过特殊的语法,将元数据直接以注解(Annotation)的形式嵌入在程序源代码和编译后的可执行代码中,开发、维护和使用较为便利,目前也得到了广泛的应用。本文也采用这种方法来提供实体类的ORM元信息。表2是采用JPA 2.1标准注解提供ORM元信息的实体类示例: 3 工作原理 目前各种ORM框架,如Java社区常用的Hibernate,MyBatis等,其基本工作原理类似,如图1所示: 1)系统启动时,首先通过读取XML文件、解析代码中的注解信息等方式载入ORM元信息;2)当系统需要进行数据持久化时,调用ORM框架提供的API接口方法;3)ORM框架一方面通过反射机制访问实体对象中的相应属性或方法,从而实现对象中信息的读取或更新;另一方面根据元信息动态生成SQL语句,访问关系式数据库进行数据存取。 为了解决ORM框架在运行时工作带来的运行效率低下的问题,本文提出的EasyPersist工具,其工作原理与传统的ORM有较大的区别,如图2所示: 1)EasyPersist工作在代码开发阶段。开发人员完成了实体类和ORM元信息的开发后,手动执行EasyPersist工具; 2)EasyPersist工具读入实体类的源代码,分析其注解信息,从而得到ORM元信息,建立ORM映射模型; 3)EasyPersist根据ORM映射模型,生成实体类对应的数据持久化源代码(以数据持久化类的形式); 4)开发人员在程序中使用自动生成的源代码。 由于EasyPersist自动化生成相关的源代码,因此其开发的效率与使用ORM框架相比,是相同的;同时,由于生成的源代码中未对数据库操作和数据库转换操作进行额外的封装,因此它的执行效率与手工编写的代码相当,比传统的ORM框架要更加高效。 4 EasyPersist工具设计与实现 4.1 EasyPersist的整体结构 EasyPersist的整体结构如图3所示,主要包括四大子模块,即: 1)XML配置文件解析模块(Config Parser),负责解析XML配置文件,获取实体类所在包和持久化代码输出目录等相关配置信息; 2)实体关系模型仓库(Mapping Repository),用于储存各实体类对应的ORM元信息; 3)源代码分析模块(Package Scaner),用于分析实体类的源代码,获取实体类对应的ORM的元信息,并存储到实体关系模型仓库中; 4)代码生成模块(Persistor Generator),从实体关系模型仓库中读取各实体的ORM元信息,生成最终的持久化代码。 4.2 源代码分析算法 源代码分析模块是EasyPersist的核心模块之一,其作用是对程序源代码进行分析,找出实体类以及对应的ORM元信息。其核心算法如表3所示: 4.3 代码生成算法 代码生成是EasyPersist的另一个核心模块,其作用是根据已有的ORM元信息,生成对应实体的持久化代码。其核心算法见表4。 4.4 条件查询与分页 除了基本的CRUD操作外,在信息系统中还经常需要查找属性符合特定条件的实体,即进行条件查询操作。由于每一个实体类都可能会有多个属性,将各属性的所有可能组合都一一列举出来分别生成一个对应的查询方法,会导致生成的代码过分庞大。因此,需要通过某种方式,在ORM元信息中指明可能的条件查询方式。 实际上,在关系数据库的查询中,往往采用建立索引的方式来对条件查询进行优化。因此,可以在实体类代码中嵌入JPA2.1标准中的@Index和@UniqueContstraint等注解,以提供数据库中的索引信息,如表5所示。 EasyPersist在源代码分析时读取这些元信息,然后在代码生成根据元信息推断出信息系统可能的条件查询方式,并生成相应的条件查询代码。 根据索引和被索引字段类型的不同,其可能的条件查询方式和返回结果也不同: 1)对于唯一型索引,其可以有两种查询方式:a.要求被索引字段(属性)的值与查询关键字相等,此时查询结果应是唯一的;b.要求被索引字段(属性)的值位于查询关键字限定的某个范围内,此时查询结果是一组实体对象。因此,对于此种索引,可以针对两种情况分别生成两个查询方法。 2)对于非唯一型索引,不管是要求与查询关键字相等还是要求位于某一范围内,其查询结果都可能是一组实体对象。因此。这种索引只需要生成一个查询方法。 此外,针对信息系统中常见的分页要求,EasyPersist一方面在返回一组对象的查询方法中增加了相关的参数,另一方面为每个索引生成一个对应的计数方法。 最终得到的条件查询方法生成算法如表6所示。 5 试验 笔者在Core i5,16G内存,Windows 7 64位, JDK 1.8.0_60 64位环境下,对使用Hibernate框架编写和用EasyPersist生成的持久化代码进行了对比测试。具体测试内容如下: 1)实验一,将1000个实体对象依次保存到空的数据表中,记录所用总时间和内存; 2)实验二,从数据表中读取全部的1000条记录,重复1000次,记录所用总时间和内存; 3)实验三,从数据表中读取所有符合特定查询条件的记录(有索引),重复1000次,记录所用总时间和内存。 三项实验分别进行了1000次,结果如表7-9所示 从实验结果可见,与Hibernate框架相比,使用EasyPersist生成的持久化代码,其运行时间更短,使用的内存资源也更少;特别是进行数据的读取查询处理时,在内存资源的使用上有近百倍的差别。因此,EasyPersist具有明显的优越性。 6 结束语 本文针对以Hibernate为代表的 ORM框架的运行时速度较慢,资源占用较高等缺点,提出了一种在代码开发时通过源码分析提取ORM元信息,从而自动生成数据持久化源代码的ORM开发方法,并开发出了相应的EasyPersist工具。实验证明,使用该工具生成的数据持久化代码,与使用传统ORM框架开发的数据持久化代码相比,开发和维护效率相当,而在运行速度和内存占用上都有较明显的改善,从而可以减少系统对运行环境的要求,更加有利于信息系统在基层林业部门的普及和推广。 注释: ① http://www.jetbrains.com/idea. ② https://github.com/royqh1979/EasyPersist. 参考文献: [1] Masliankoa P P, Maistrenkoa A S. A system of entities for enterprise business models[J]. Cybernetics and Systems Analysis, 2012, 48(1): 99-107. [2] Wang Y, Xu,Y. Research of solutions of object-relational mapping in JAVA platform[C]//2011 International Conference on Control, Automation and Systems Engineering, Singapore, Singapore, 2011. [3] Zyl P V, Kourie D G.The influence of optimisations on the performance of an object relational mapping tool[C]//Proceedings of the 2009 Annual Research Conference of the South African Institute of Computer Scientists and Information Technologists, Vanderbijlpark, Emfuleni, South Africa. ACM, 2009. [4] 李杰. 基于ORM的轻量级数据持久化技术研究及应用[J]. 计算机科学, 2010, 37(9): 190-193, 208. [5] O'Neil E. Object/Relational mapping 2008: Hibernate and the entity data model (EDM)[C]//2008 ACM SIGMOD International Conference on Management of Data, Vancouver, BC, Canada. 2008. [6] 程文波, 卢涵宇. 一种新的数据持久层设计方法与实现[J]. 微电子学与计算机, 2011(7): 28-30. [7] Gotz S, Kuhn T. [email protected] for object-relational mapping supporting schema evolution[C]//10th International Workshop on [email protected], MRT 2015 - co-located with the 18th International Conference on Model Driven Engineering Languages and Systems, MoDELS 2015, September 29, 2015, Ottawa, ON, Canada. CEUR-WS, 2015. [8] Kurtev I. Application of reflection in a model transformation language[J]. Software & Systems Modeling, 2009, 9(3): 311-333. [9] Cvetkovi S, Jankovi D. A Comparative Study of the Features and Performance of ORM Tools in a .NET Environment[C]// Dearle A, Zicari R V. Objects and Databases: Third International Conference, ICOODB 2010, Frankfurt/Main, Germany, September 28-30, 2010. Proceedings. Berlin, Heidelberg: Springer Berlin Heidelberg, 2010:147-158. [10] Gruca A, Podsiadlo P. Performance Analysis of .NET Based Object-Relational Mapping Frameworks[C]//Beyond Databases, Architectures and Structures - 10th International Conference, BDAS 2014, Proceedings. Springer Verlag, 2014. [11] Yousaf H. Performance Evaluation of Java Based Object Relational[J]. Mehran University Research Journal of Engineering & Technology, 2013, 32(2): 160-166. [12] Chen T H, Shang W. Detecting performance anti-patterns for applications developed using object-relational mapping[C]//Proceedings of the 36th International Conference on Software Engineering, Hyderabad, India. ACM, 2014. [13] 黄强, 张晓梅. 一个基于类型元数据的轻量级ORM框架设计[J]. 计算机工程, 2007(22): 54-56,59. [14] 何成万, 张立军. 基于元数据和反射的面向方面软件演化方法[J]. 电子学报, 2011(8): 1771-1777. [15] Prakash S, Saini J. Features of Annotations and their Applications[J]. International Journal of Computer Applications, 2011, 16(8): 14-21. |
随便看 |
|
科学优质学术资源、百科知识分享平台,免费提供知识科普、生活经验分享、中外学术论文、各类范文、学术文献、教学资料、学术期刊、会议、报纸、杂志、工具书等各类资源检索、在线阅读和软件app下载服务。