APP下载

业务逻辑层与数据访问层的Nosql模型研究

2018-03-29吴勤庄红铁治欣刘晶晶

软件 2017年8期
关键词:代码排序逻辑

吴勤 庄红 铁治欣 刘晶晶

摘要:业务逻辑层(BLL)与数据访问层(DAL)是MVC的核心层,BLL与DAL的实现,使Web应用系统具有更好的低耦合度,高模块化程度,易维护,易扩展。通过对传统的BLL与DAL的模型结构的进一步研究,分析出传统BLL与DAL存在重复率高,利用率低的缺陷。因此提出在Web應用中基于JPA规范和泛型程序设计,采用Spring Data JPA的BLL与DAL层的Nosql模型。通过该模型应用和模型评估,发现该模型与传统的模型结构相比,代码量少,利用率高,提高了Web应用软件的开发效率。

关键词:业务逻辑层;数据访问层;通用泛型;JPA规范;SpnngDataJPA;Nosql模型中图分类号:TP311.5文献标识码:ADOI:10.3969/j.issn.1003-6970.2017.08.008

本文著录格式:吴勤,庄红,铁治欣,等.业务逻辑层与数据访问层的Nosql模型研究[J].软件,2017,38(8):4349

引言

BLL与DAL是MVC模式的重要两个分层,将传统模式下业务逻辑和数据操作有效的划分开,有效的解决了两者混杂导致的系统难于维护和拓展的弊端,大大提高了开发效率和系统性能。泛型是JDK1.5的新特性,允许编写可作用于任意类型的类,直到声明了类的实例,才指定特定的类型。使用泛型的主要优点是能够使我们在编译时而不是运行时检测出错误。JPA是Java官方提出的、随Java EE5规范一同发布的,在此之前,已经存在很多ORM框架了,他们都有不同的实现,这也是JAP出现的必然条件,它规范ORM框架,是ORM框架有统一的接口和用法。文献[5-6]对数据持久层提出使用Spring Data和JPA构建持久层这一方法,阐述这种方法让数据访问层开发量变少的原因,并且分析它访问数据库的过程。将这种方法应用到Java EE系统中,与传统的构建持久层方法相比,这种方法使开发人员从繁琐的数据访问层中解放出来,不需要写大量的代码,只需要少量的代码就可以实现对数据库的访问,但是业务逻辑层还需要写大量的代码来完成项目的开发[、15]。文献[17-19]讲述了一种动态生成sql语句的方法。基于此,提出一种在Web应用中基于Spring Data JPA、通用泛型的BLL与DAL层的Nosql模型,从而减少大部业务逻辑层和数据访问层的代码。

1 BLL与DAL层泛型引入

1.1 传统BLL与DAL层设计

业务逻辑层(BLL)是应用系统中的核心,负责处理系统具体的业务逻辑。在该实现框架中,业务逻辑层由纯业务逻辑类和AOP处理程序组成。纯业务逻辑类负责完成与具体业务密切相关的业务逻辑处理,AOP处理程序负责权限管理、事务管理、日志管理等非纯业务的逻辑处理。每个业务模块拥有独立的业务处理逻辑,每个业务需要一一的针对单一的对象进行业务处理操作。因而会造成重复的代码,代码利用率不高,降低了开发效率。

数据访问层主要是封装业务处理逻辑与数据存储层之间的交互过程,向业务逻辑层提供数据服务。在具体的应用开发中,数据访问层有多种不同的实现方式。业务模块根据业务逻辑,调用对应DAO接口,实现接口,最后实现ORM。传统业务逻辑层与数据访问层的业务过程如图1所示:

在项目开发过程中,传统的BLL与DAL层设计,代码重复率高,利用率低,从而开发效率低。1.2Java程序中泛型设计Java5.0的新特性是引入了泛型,泛型允许编写可作用于任意类型的类,但是直到声明了类的实例,才指定特定的类型。因为此类型不是作为类定义的一部分而指定的,所以该类一般对任意指定类型起作用。这个能力使我们可以定义带泛型类型的类或是方法,随后编译器会用具体的类型来替换它。因此泛型可以使我们在编译时而不是在运行时检测出错误。泛型是类型的安全性增加。

1.3 将Java泛型引入BLL与DAL层

图一中是传统的BLL与DAL层,它可以完成系统业务以及数据的访问,但在开发中存在着一些不足。第一,BLL与DAL层的代码重复率过高,开发效率低;此外,实现类的方法使代码显得比较繁琐;第三,主键值以及实体类型需要指定,频繁的转换返回结果值的类型。通过引用泛型,从而解决上述一系列的问题,而且泛型可以使代码在编译时,而不是在运行时检测出错误。

与传统的BLL与DAL层设计相比,构建泛型是类型安全、代码精简的设计方式,在业务庞大项目中,代码明显的减少,对于项目成本,时间,工作量带来了有利的条件。通过封装BLL与DAL层基类泛型,从而达到优化BLL与DAL层设计目的。

2 基于JPA规范的SpringDataJPA的运用

2.1 JPA规范介绍

JPA(Java Persistence API)是JavaEE平台标准的规范,将得到服务器的支持。在吸收现有框架的基础上,是一个易于使用、伸缩性强的规范。JPA规范本质上是一种ORM规范,它不是ORM框架,因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现,例如,JBoss应用服务器底层就以Hibernate作为JPA的实现。即JPA规范中提供的只是一些接口,接口不能直接拿来使用。虽然应用程序可以面向接口编程,但JPA底层一定需要某种JPA实现,否则JPA依然无法使用。因此开发者面向JPA规范的接口,但底层的JPA实现可以任意切换Hibernate、EBATIS、TopLink等。

2.2 Spring Data JPA与JPA规范的关系

Spring datajpa的目标是简化关于各种持久存储数据访问层而努力。ORM框架都实现了JPA规范,但是在不同ORM框架之间切换是需要编写的代码有一些差异,而通过使用Spring DataJpa能够方便在不同的ORM框架中间进行切换而不要更改代码。并且Spring DataJpa对Repository层封装的很好,可以减少很多的麻烦。

Spring Data JPA与JPA规范的关系如图2所示:

3 BLL与DAL层设计基于Spring Data

JPA、通用泛型的模型实现

在项目开发中,以Java泛型与Spring Data JPA

為基础,在业务逻辑层与数据库访问层构建Nosql模型。

3.1 相关配置

首先,配置JPA标准配置文件persistence.xml。然后,在Spring配置文件applicationContext.xml中增加JPA支持,即实体管理器工厂Entity Manager Factor,它是获得实体管理器Entity Manager对象的入口?最后,在Spring配置文件中配置启用扫描并自动创建代理的功能,Sprmg为声明的接口创建代理对象。配置了后,Spring初始化容器时将会扫描base-package指定的包目录及其子目录,为继承Repository或其子接口的接口创建代理对象,并将代理对象注册为Spring Bean,业务层便可以通过Spring自动封装的特性来直接使用该对象。

3.2 BLL层与DAL层的Nosql模型设计

3.2.1 模型中变量定义

定义1对象列操作{EQ,NOTEQ,LIKE,GT,LT,GTE,LTE,IN,NULL,NOTNULL}。

其中,EQ:等于;NOTEQ:不等于;LIKE:比较较相似的值;GT:大于

LT:小于;GTE:大于等于;LTE:小于等于;IN:

指定值在已指定一个值的列表

NULL:空;NOTNULL:不为空

3.2.2 模型思想

逻辑层建立一个公共的泛型业务逻辑处理模型,实体业务逻辑类继承公共泛型模型,通过反射,获得指定类的父类的泛型参数的实际类型,从而完成实际类型的业务逻辑操作。公共的泛型业务逻辑处理模型实现添加、修改、删除、查询。添加通过系统调用传递过来的封装实体参数完成新增功能。修改根据系统传递过来修改过的实体进行保存。删除根据系统调用传递过来的参数id或整个实体进行删除。查询通过系统调用传递过来的参数,参数为查询条件操作key-value集合,以及排序操作集合。然后,根据条件操作进行动态的查询条件拼接,或排序操作进行分页排序,详细说明参见算法1和算法2。最后,调用数据访问层Spring Data JPA相应基本操作接口,从而实现Nosql的操作。

算法1分页排序算法

算法参数:页码,分页数量,排序的对象集

//排序的对象集,为排序对象的集合,排序对象包括属性和方向

返回值:Pageable型对象过程:

Begin

1、 Sortsort=null//仓1J建——个org.springframework.data.domain.Sort的sort排序对象

2、 If“排序的对象集”为空,排序根据数据库id排序

3、 Else“排序的对象集”不为空且大小大于0

4、 获取“排序的对象集”的第一个排序对象属性和方向

5、 If升序=排序的对象集升序方向

6、 sort=newSort(升序,属性)

7、 elsesort=newSort(降序,属性)

8、 for“排序的对象集”//从排序的对象集for第二个对象开发for循环直至结束

9、 获取“排序的对象集”的下一个排序对象属性和方向

10、 If升序=排序的对象集升序方向sort.and(升序,属性)

12、 elsesort.and(降序,属性)

13、 返回一个new Page Request(页码-1,分页数量,sort)即Page Request通过参数生成Pageable对象;

//Spring DataJpa提供了Page Request的具体实现,通过提供分页以及排序信息即可。Pageable是Spring Data库中定义的一个接口,该接口是分页相关信息的一个抽象,通过该接口,可以得到和分页相关所有信息(例如页码、分页数量等),这样,Jpa就能够通过pageable参数来得到一个带分页信息的Sql语句。

End

算法2动态查询条件拼接器算法

算法参数:查询条件key-value集合,泛型类返回值:拼接好的条件组合

//key形如LIKE_topic,其中LIKE为操作,topic为操作字段,value为值。或者key形如为EQ_user.name,其中EQ为操作,user.name为操作字段,user连接的子表,name为子表的字段名

过程:

Begin

1、声明包含属性“对象列名称”,“对象列值”,“对象列操作”,“加入的其他表对象标志”的一个“条件对象”

2、 声明一个Map型“条件对象型集合”

3、 Forkey-value集合

4、 获取key与value值,如果value为空continue

继续

5、 对value进行Java标准语言类型处理

6、 根据key分解出条件对象的属性以及对应的value,赋值“条件对象”属性

7、 添加到Map型“条件对象型集合”

8、 ForMap型“条件对象型集合”

9、 获取“条件对象”列名称(形如:user.name或topic)拆分为“条件对象”列名称数组

10、 If“条件对象”的“加入其他表对象标志”不为空

11、 创建一个javax.persistence.criteria.Predicate类型的predicates对象集合

12、 If对象列名称数组不为空,且大于1

13、 If“加入其他表对象标志”为join

14、 定义了查询的FROM子句中能够出现的类型及其对象列名expression[3-4]//该句实现连表功會b,expression为javax.persistence.criteria.Path的一个对象

15、 Else定义了查询的FROM句中能够出现的类型及其对象列名expression

16、 switch(对象列操作){caseEQ:predicates.add(builder.equal(expression,对象列值));//builder为javax.persistence.criteria.CriteriaBuilder创建的一个对象

break;

caseNOTEQ:

predicates.add(buMer.notEqual(expression,对象列值));

break;caseLIKE:

predicates.add(builder.like(expression,对象列值+n%));

break;caseGT:

predicates.add(builder.greaterThan(expression,对象列值));

break;caseLT:

predicates.add(builder.lessThan(expression,对象列值));

break;caseGTE:

predicates.add(builder.greaterThanOrEqualTo(expression,对象列值));

break;caseLTE:

predicates.add(builder.lessThanOrEqualTo(expression,对象列值));

break;caseIN:

Inin=builder.in(expression);

“对象列值”转化为对象列值数组

For对象列值数组

in=in.value(值);

predicates.add(in);

break;

case

NULL:predicates.add(builder.isNull(expression));

break;

caseNOTNULL:

predicates.add(builder.isNotNull(expression));break;

}

//将所有条件用and联合起来

17、 if(predicates.size()>0)

18、 returnbuilder.and(predicates.toArray(newPredicate[predicates.size()]));

//返回一个拼接好的条件组合

End

3.2.3 Nosql模型说明

参考文献[5-6]对Spring Data和JPA进行了一些研究,并阐述了Repository基本的用处,提供了Repository最基本的数据访问功能,对下面的几个方面做详细的使用介绍:1、Cmd Repository继承Repository实现了一组增加删除修改查询相关的方法。

2、Paging And Sorting Repository继承Cmd Repository,

實现了一组分页排序相关的方法。3、Jpa Repository继承Paging And Sorting Repository,实现一组JPA规范相关的方法。上述为基本的功能,碎片化形式在项目开发中,没有集成和优化处理,因而降低了开发效率,下面提出了一种Nosql模型,它对基本数据访问功能进行了优化和多功能化研究与处理。下面是Nosql模型包含的主要的部分。

其中:search Params:查询条件key-value集合;final Classclazz:是需要反射的类,该类必须继承范型父类,通过反射,获得指定类的父类的泛型参数的实际类型,从而减少代码量;

build Page Request:采用算法1完成分页排序算法;build Specification:采用算法2完成动态查询条件拼接;

findAll()、save(entity)、delete(id)、deleteAll()page Number:页码page Size:分页数量

Specification:org.springframework.data.jpa.domain.Specification的一个类对象

1、 实现多功能排序查询

publicListgetList(Map

Sortsort,finalClassclazz){

Specificationspec=buildSpecification(searchParams,clazz);

returnthis.getDao().findAll(spec,sort);

//多功能查找所有实体}

2、 实现多功能分页查询

publicPagegetList(Mapclazz){PageRequestpageRequest=buildPageRequest(pageNumber,pageSize,sortType);

Specificationspec=buildSpecification(searchParams,clazz);

returnthis.getDao().findAll(spec?pageRequest);

}

3、 实现列表查询

publicListfindAll(){

Iterableiter=this.getDao().findAll();

returnLists.newArrayList(iter);}

4、实现排序列表查询

publicListfindAll(Sortsort){

Iterableiter=this.getDao().findAll(sort);

returnLists.newArrayList(iter);

}

5、 保存实体

publicvoidsave(Tentity){this.getDao().save(entity);

}

6、 根据id删除

publicvoiddelete(Longid){this.getDao().delete(id);

}

7、 删除所有

publicvoiddeleteAll(){

this.getDao().deleteAll();

}

3.2.4 模型应用

在业务逻辑BBL层,设计一个基于通用泛型的业务逻辑处理模型,完成整个项目的业务逻辑处理,最终达到大部分功能Nosql的实现。

在DAL层,设计基于Spring Data JPA的方法声明即可,然后完成数据访问。

模型应用过程如图3所示:

项目通过图3Spring MVC Controller控制器,在BLL层找到对象对应的模型逻辑业务处理接口,如果业务逻辑简单,则进入DAL层进行数据访问处理,再到ORM框架处理。否则进入Nosql模型,进行业务处理,模型处理完后找到对应的数据访问接口,最后通过SpringDataJPA选择相应的ORM框架处理即可,项目的功能即可完成。

项目应用中泛型的模型设计举例如下:

BLL层基于泛型的模型设计

publicabstractclassNosqlService

dsBaseDao

DAL层泛型基础接口设计publicinterfaceBaseDaoextendsJpaRepository,paSpecificationExecutor

{}

3.2.5 模型评估

模型评估采用CoCoMo(Constructive CostModel)模型,中文为构造性成本模型。它是一种精确、易于使用的,基于模型的成本估算方法,由Boehm提出[2?23]。模型评估数据来源完成同一项目的实际数据导出。其中一个表示同一项目未采用Nosql模型,一个是采用Nosql模型。采用所选取的样本数据基本上具有如下的特征:1、相同的项目;2、选取基本上来源于人月的项目的数据,相同的人员素质;3、使用相同的平台,在同一个平台开发所有的项目;4、开发所采用的语言以及项目所采用的管理流程相同。

CoCoMo模型,用于估算整个系统的工作量和软件开发所需要的时间。

E=a(L)b (1)

D=cEd (2)

N=i (3)

其中:E表示工作量,单位是人月(PM);

D表示开发时间,单位是月;

L是项目的代码行估计值,单位是千行代码;

N表示项目开发人数。

a、b、c、d是常数,取值如表1所示。

根据同一个项目开发的数据来源,一个未采用Nosql模型的代码行数L=26.8千行代码,与同一个项目采用Nosql模型的代码行数L=15.6千行代码进行评估。

由上述评估模型计算,得到的模型评估结果如表2所示:

其中:

A:同一个项目表示未采用Nosql模型。

B:同一个项目表示采用Nosql模型。

L:是项目的代码行估计值,单位是千行代码。

E:表示工作量,单位是人月(PM)。

D:表示开发时间,单位是月。

N:表示项目开发人数。

观察表2,将未采用Nosql模型和采用Nosql模型开发的Web应用进行比较,发现未采用Nosql模型开发的Web应用,项目的代码量总数较大,开发的时间周期较长,参与开发项目的人数较多。而采用Nosql模型的Web应用,能够以较少的代码总数,用较短的开发周期以及较少的开发人员完成同樣的工作。综上可以看出,采用Nosql模型开发Web应用可以更加有效的提高软件开发效率。

4 结论

针对项目代码量大,代码利用率低,开发效率低,提出了业务逻辑层的处理模型和数据访问层的处理策略。首先介绍了BLL与DAL层泛型引入。然后,对基于JPA规范的Spring Data JPA的运用做说明。接下来,提出了基于JPA规范、泛型的业务逻辑处理模型,最后,对模型应用做了介绍,并且对模型进行评估。通过该Nosql模型,使用者不知道具体的业务逻辑操作细节,通过业务逻辑需求,调用逻辑模型,完成业务逻辑操作。该模型要少量的代码就可以实现业务逻辑操作和数据库的访问,从而使开发者可以更加专注于业务的分析,节省了开发人员熟悉项目架构的时间,降低了项目开发的成本,提高了开发的效率。下一步工作将继续研究如何在更复杂的个性化业务上,提供相应的通用策略,促进项目更好,更快的开发。

猜你喜欢

代码排序逻辑
刑事印证证明准确达成的逻辑反思
排序不等式
逻辑
创新的逻辑
恐怖排序
创世代码
创世代码
创世代码
创世代码