实现ORM映射的中间件比较多,常见的有EF/EF Core、NHibernate、 MyBatis、Dapper、FreeSql、PetaPoco、linq2db等,下面对在项目中使用较多的几个ORM框架进行介绍。
一、NHibernate
Hibernate是一个开放源代码的ORM框架,是一个不依赖于其它平台的轻量级中间件。Hibernate对JDBC进行了非常轻量的封装,将JavaBean和数据库的表建立对应关系,从而提供了使用面向对象编程思维来操纵数据库的方式。Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序中使用,也可以在Web应用中使用,最重要的是可以在JavaEE架构中完成数据持久化的重要工作[1]。
Hibernate的创始人是Gavin King,其也是EJB3.0专家委员会的成员、JBoss核心成员之一。2001年,Gavin King使用EJB的Entity bean 1.1时,觉得开发效率太低,于是便开始试图寻找更好的方案。经过两年多的努力,在2003年,Gavin King和他的开发团队推出了Hibernate,Hibernate在当时也成为了最流行的开源ORM解决方案[2]。
①Hibernate的优点
Hibernate功能强大,是Java应用与关系数据库之间的桥梁,较之JDBC方式操作数据库,代码量大大减少,提高了持久化代码的开发速度,降低了维护成本。Hibernate支持面向对象的特性,如组合、继承、多态等,使得开发人员不必面向业务领域的对象模型和面向数据库的关系数据模型来回切换,方便开发人员进行领域驱动的面向对象的设计与开发。可移植性好。系统不会绑定在某个特定的关系型数据库上,对于系统更换数据库,通常只需要修改Hibernate配置文件即可正常运行。Hibernate框架开源免费,可以在需要时研究源代码,改写源代码,进行功能的定制,具有可扩展性。
② Hibernate的缺点
不适合以数据为中心大量使用存储过程的应用。大规模的批量插入、修改和删除不适合使用Hibernate。
基于Hibernate在Java开发领域的成功运用,开源组织使用了C#语言按照Hibernate的架构开发了NHibernate的ORM映射中间件,希望Hibernate能在 .NET软件开发的领域也能得到相同的优点。
NHibernate是一个面向.NET框架的开源对象关系映射中间件,是一个功能较为完整且成熟的开源ORM框架,NHibernate也提供了可跨平台的NHibernate Core版本,并将其运用于工程项目中的案例也比较多(参考https://nhibernate.info)。开源社区在NHibernate的基础上,进一步对其功能进行封装后,形成了Castle框架,Castle框架解决了NHibernate的一些缺陷以及提高了NHibernate的易用性。
NHibernate在应用程序中充当了数据访问层的作用,将关系数据库映射 成应用程序中的持久化对象,其使用app.config或web.config来进行数据库的配置,在映射实体类时使用xml格式的文件作为映射配置文件。图1 所示为NHibernate的整体架构图,此架构图显示了NHibernate使用数据库和配置文件来向应用程序提供持久化服务。图2是NHibernate架构的更为详细的设计。
图1 NHibernate的整体结构[3]
图2 NHibernate体系架构
在.NET程序开发中当需要使用NHibernate时,可通过VS开发环境提供的NuGet包管理器引入NHibernate的包,关于NHibernate的具体运用可参考NHibernate所提供的参考文档。
图3 在VS开发环境中引入NHibernate包
二、MyBatis
MyBatis 也是一款较为优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis可以通过简单的XML或注解来配置和映射原始类型、接口和Java POJO(Plain Old Java Objects,普通老式Java对象)为数据库中的记录[4]。
MyBatis可以创建自己的数据库连接池,使用XML配置文件的形式对数据库连接进行管理。MyBatis支持动态列、动态表名存储过程等,同时提供了简易的日志、缓存和级联操作功能。MyBatis具有自身独立的功能架构,具体如图4所示[5]。
图4 MyBatis功能架构图
MyBatis将SQL语句配置在XML中来避免向代码中添加SQL语句的硬编码问题,通过MyBatis提供的输入参数映射方式,将参数自由、灵活地配置在SQL语句配置文件中。MyBatis的整体运行流程紧紧围绕mybatis-config.xml配置文件及SQL映射配置文件mapper.xml展开[6],其工作原理如图5所示[7]。
图5 MyBatis工作原理图
三、Entity Framework
1、Entity Framework 概述
Entity Framework(实体框架,简称EF)是微软开发实现的一个ORM框架,它支持 LINQ查询、更改跟踪、更新和架构迁移等。EF适用于较多数据库,包括SQL Server数据库(本地和Azure)、SQLite、MySQL、PostgreSQL和Azure Cosmos DB等[8]。
EF在2008年首次作为.NET Framework的一部分进行发布,此后对其进行了持续的更新,主要经历了以下几个演变[9]:
1)EF的第一个版本到EF 4作为.NET框架的一部分完全包含在.NET框架中发布,这部分旧版本现已不建议使用。
2)EF 4.1、4.2、4.3和5.0的部分功能在.NET 框架中发布,但有部分功能却以NuGet包的形式提供,这些版本现在已不受技术支持。
3)EF 6.0、6.1、6.2、6.3和6.4则不包含在.NET 框架中发布,其完全以NuGet包的形式向开发者提供,称这些版本为Entity Framework 6.x,目前最新版本为6.4.4。Entity Framework 6.x的功能较为稳定,但这些版本不支持跨平台的应用开发,随着.NET框架对跨平台开发的支持,Entity Framework 6.x的功能将不再开发升级。
4)基于.NET跨平台应用开发的目的,微软对EF的代码进行了完全的重新编写,其产品也以Entity Framework Core(EF Core)命名,EF Core也以NuGet包的形式向开发人员提供。EF Core是微软当前最新的ORM框架,其功能也在不断的更新,EF Core也被建议在新的项目开发中使用。在本书后面的章节我们也将基于EF Core来进行阐述。
EF Core是当前.NET软件开发领域中最流行的ORM框架,相比与EF历史的版本,EF Core更加的轻量级,且可扩展和跨平台。EF Core主要的版本有[10]:
表1 EF Core主要版本
版本
目标框架
技术支持截止时间
特性介绍
EF Core 7.0
.NET 6
2024-5-14
支持数据库JSON 列的映射、查询;提升SaveChanges性能;存储过程映射等。
EF Core 6.0
.NET 6
2024-11-12(LTS)
支持.NET 6.0目标框架;支持SQL Server 临时表;LINQ 查询增强功能等。
EF Core 5.0
.NET Standard 2.1
2022-5-10
新增多对多映射功能,无需显示映射联接表;拆分Include的关联查询成两个独立查询,提升查询性能;每个类型映射一张表 (TPT);支持数据库排序规则等。
EF Core 3.1
.NET Standard 2.0
2022-12-13(LTS)
修复了超过150个存在的bug。
EF Core 3.0
.NET Standard 2.1
2020-3-3
查询时不再在客户端上计算LINQ查询;支持Cosmos数据库;支持C#8.0异步查询、可为空类型等。
EF Core 2.2
.NET Standard 2.0
2019-12-23
支持空间数据、查询标记;提供更强的兼容性等。
EF Core 2.1
.NET Standard 2.0
2021-8-21
增加延迟加载功能;LINQ查询时支持GroupBy转换;查询时数据类型转换;优化关联子查询等。
EF Core 2.0
.NET Standard 2.0
2018-10-1
支持.NET Standard 2.0标准;增强LINQ查询,如like查询;增加全局查询筛选器功能;建立DbContext连接池等。
EF Core 1.1
.NET Standard 1.3
2019-6-27
修复了EF Core 1.0中存在的一些bug
EF Core 1.0
.NET Standard 1.3
2019-6-27
第一个轻量级、可扩展的.NET跨平台ORM框架。
EF Core的特点包括:
1)支持跨平台:EF Core基于.NET Standard的标准,从设计到实现都要求支持跨平台,可以运行了 Windows、Linux、Mac等平台上。
2)使用LINQ查询数据。EF Core与LINQ查询结合,可以方便的查询对象数据集合。
3)EF默认使用自动管理事务,在需要程序开发人员手工管理事务时,也提供了事务管理的方法。
4)EF Core使用DbContext上下文管理对象的状态,并对对象的变更状态进行跟踪,需要持久化对象时,可使用SaveChanges方法将对象的变化批量提交到数据库中保存。
2、Entity Framework的体系结构
Entity Framework的体系结构建立在ADO.NET数据提供程序之上,图7.1是Entity Framework的体系结构[11]。
图6 Entity Framework体系结构
LINQ to Entities:提供语言集成查询(LINQ)支持,用于查询在概念模型中定义的实体类型。
实体SQL(EF 6.x中):是一种类似于SQL的语言,用于在EF中查询概念模型。概念模型将数据表示为实体和关系,而实体SQL让熟悉SQL的用户按照SQL的方式查询这些实体和关系。
EntityClient数据提供程序:是一种数据提供程序, EF的应用程序使用该提供程序访问在概念模型中描述的数据。EntityClient数据提供程序负责管理连接和管理事务,可在特定的ADO.NET数据提供程序基础上,管理EF与关系数据库的连接,在事务管理方面有自动和显式两种方式。EntityClient数据提供程序可以创建实体SQL查询,在执行数据查询,将查询请求经过解析并转换为规范命令目录树,所有后续处理都在该命令目录树上执行,最后将查询转换成底层数据库可以理解的SQL语句。
Object Servies:是提供访问数据库数据,并接收返回数据的入口,这是将EntityClient数据提供程序返回的数据转换为实体对象结构的过程。
ADO.NET数据提供程序:该层使用标准的ADO.NET与数据库通信。ADO.NET是一组为.NET编程人员提供数据访问服务的类,它提供了丰富的组件来创建分布式、数据共享的应用程序。ADO.NET提供了适用于与数据库保持连接的和断开连接的两种组件来为应用程序提供数据操作,其体系结构如图7所示[12]。
图7 ADO.NET体系结构
3、Entity Framework开发流程
由于EF Core在Database First模式支持有限,在使用EF Core开发应用程序时,一般按照以下的流程进行。
1)引入EF Core开发包
要在项目中使用EF Core,首先需要在项目中引入EF Core的开发包,通过项目的包管理器,
2)从EF提供的DbContext派生上下文管理类
3)配置数据库连接信息
4)定义领域类及类间的关联关系
5)定义实体类与关系表的映射、实体关联关系
6)编写领域对象的数据查询、更新、删除等业务逻辑方法
[1] 工业和信息化人才交流中心蓝桥杯软件大赛专家委员会.使用Hibernate框架轻松连接数据库[M].北京:电子工业出版社,2013,2.
[2] 肖睿,郭泰,王丁磊.SSH框架企业级应用实践[M].北京:人民邮电出版社,2018,70-72.
[3] NHibernate Reference Documentation[EB/OL][2023-4-22].https://nhibernate.info/doc/nh/en/nhibernate_reference.pdf
[4] https://mybatis.org/mybatis-3/zh/index.html
[5] 千锋教育高教产品研发部. Java EE(SSM)企业应用实战[M].北京:清华大学出版社,2019,3.
[6] 张桓,刘仲会,丁明浩. SSM轻量级框架应用开发教程[M].北京:人民邮电出版社,2020,90.
[7] 黑马程序员. Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)[M].北京:人民邮电出版社,2017,87.
[8] https://learn.microsoft.com/zh-cn/ef/core/providers/?tabs=dotnet-core-cli
[9] https://learn.microsoft.com/zh-cn/ef/efcore-and-ef6/support
[10] https://learn.microsoft.com/zh-cn/ef/core/what-is-new
[11] https://learn.microsoft.com/zh-cn/dotnet/framework/data/adonet/ef/overview
[12] Vidya Vrat Agarwal. C# 2012 数据库编程入门经典(第5版)[M]. 北京:清华大学出版社,2013,139-143.