Entity Framework_成功针对多种数据库使用实体框架(EF)

本文探讨了使用实体框架(Entity Framework, EF)开发应用程序时,针对不同数据库(如Oracle、MySQL、PostgreSQL和SQLite)而非仅限于Microsoft SQL Server时所面临的问题。文章覆盖了模型开发、使用多种数据库的应用程序、数据类型、并发检查、性能等方面。
原文地址:http://www.infoq.com/articles/multiple-databases


ORM 用户已经习惯于处在 .NET 和 LINQ 角度思考问题,缺忘记了特定数据库的细节——在功能和执行 SQL 效率上的差异。本文简要讨论一些在用户利用实体框架(Entity Framework,缩写EF)与 Oracle、MySQL、PostgreSQL 或是 SQLite 交互,而不是与 Microsoft SQL Server,开发应用程序过程中可能面临的一些问题。希望对那些为数据库创建EF的用户,和创建应用程序以支持与多个数据库(如SQL Server和Oracle)交互的用户有用。

我们将使用 Devart ADO.NET providers 来实施数据库EF提供者的例子,而不是 SQL Server,因为VS已经对提供 SQL Server 提供了相关很好的支持。


模型开发


开发者工具


目前,EF支持如下三个开发方法:Database-First(数据库优先)、Model-First(模型优先)和Code-First(代码优先)。没有最好的方法,方法的选择取决于特定应用程序的细节和领域。无论如何,用户必须面对的一个情形是,Visual Studio设计阶段模型开发提供的标准功能不够方便,或是有限,或是功能只针对 SQL Server,而不支持 Oracle。鉴于此,出现了很多第三方的解决方案:

* Devart Entity Developer 免费版为开发ORM模型提供全部的设计功能。

* Hugatti DBML/EDMX Tools 扩展标准VS编辑器的功能。

* LLBLGen Pro 是另一个可选的 EF。


一个应用程序中使用多种数据库


如果需要开发一个可以支持多个不同数据库的应用程序,那么在EF 中有很多解决方案。在EF v1/v4,开发者除了使用XML映射方法外,没有其他方法。但随着EF v4.1 的发布,使用fluent映射变得可行。

XML映射

开发人员完全可以在模型优先(Model-First)的方法下开发。或是在某个关系型数据库上先使用数据库优先(Database-First)的方法,然后再转到模型优先(Model-First),通过改变数据库连接和DLL生成模版,重新生成模型的映射和存储过程,来改变目标数据库。必须保存数据库创建 DDL SQL 脚本和生成的元数据,以便在每个阶段获得一套CSDL、MSL、SSDL文件。CSDL 和 MSL 是相同的,而 SSDL 文件对每个数据库文件都不同。进一步,形成正确的EF连接字符串必须基于特定的提供者程序连接字符串和对每个数据库所要求的资源名称,也就是说,若想生成正确的EF连接字符串,必须提供给EF要访问何种数据库,及其相应的数据库信息。以上仅仅是这个过程的简要说明。详细过程请参考: Migrating database schema from Microsoft SQL Server to Oracle using Entity Framework 和 Preparing for multiple databases

使用XML映射的好处:

* 支持EF映射的所有功能

* 当使用标准的 VS EDM 设计时,创建和编辑模型的大多数操作可以在设计器上完成

* 如果使用其他类型的代码生成,而不是标准的实体对象代码生成,那么用户可以获得POCO对象,或是自追踪实体(self-tracking entities,STE)。

* 通过编辑T4模版,自定义生成代码

使用XML映射的坏处:

* 繁琐,修改复杂

* 标准的 VS EDM 设计器缺少很多功能,不支持 XML 映射的所有功能,因此,用户必须在XML编辑器中手动修改,或是使用三方EF设计器

* T4 代码生成模版复杂,不便于修改,特别是对于 POCO和STE

Fluent 映射

fluent 映射功能变得可用后,开发针对访问多种数据库的应用程序变得异常容易。可以手动编写全部代码;也可以使用设计器和借助代码生成模版生成代码。更多资料,针对多种数据库开发一个EF代码优先(Code-First)的应用程序,请参考 Entity Framework Code-First support for Oracle, MySQL, PostgreSQL and SQLite

与XML映射相比,代码优先映射有如下好处:

* 开发过程相对容易

* 模型对象是 POCO-classes.

* 可以使用第三方EF设计器通过fluent映射开发一个模型,如 Devart Entity Developer

使用 fluent 映射的坏处:

* 如果不使用设计器和代码生成模版,手动完成这个过程,将需要带量代码

* 只支持一些映射功能。例如,存储过程、已编译的查询、复杂的实体分割则不支持

* 目前,不能使用标准的 VS EDM 设计器,通过fluent映射来开发模型。然后,用户可以通过 Entity Framework Power Tools 为数据库生成 fluent 映射代码


代码优先的行为


动态数据库删除和创建


在SQL Server的行为中,当映射到模型中相应对象的数据库对象被删除和创建时,整个数据库会被删除,之后再创建,并填充到新的表中。DatabaseExists 用于检查数据库是否存在。

这种行为并不总是最优的,这涉及权限问题。例如,在Oracle,模式(Schema)就是用户,不可能删除已经连接到数据库的这个用户,因此这个行为总是不能被执行。


注:模式(Schema)是用户使用的数据库对象的一个集合,这个集合包含了各种对象,如表、视图、序列、存储过程、同义词、索引等。模式的对象是数据库数据的逻辑结构。一个用户就是定义在数据库中的一个名字,可以连接数据库,并访问对象。模式和用户帮助数据库管理员管理数据库的安全。一个用户一般对应一个 Schema。可以简单理解为用户的 Schema 名等于用户名。例如,在 Oracle 数据库中,创建一个用户的同时为这个用户创建一个与用户名相同的 Schema,并作为该用户的缺省 Schema。如果想访问数据库中一个表,没有指明该表属于哪一个Schema,那么系统会自动在表上加上缺省的 Schema 名。比如,访问 scott 用户下的emp表“select * from emp”,其实,完整的写法为“select *from scott.emp”。一个对象的完整名称为“Schema.object”,而不是“user.object”。


这就是为什么 Oracle、MySQL、PostgreSQL 和 SQLite有三种删除行为。开发者自行选择使用哪一个:

* Model Objects Only - 只有被映射到模型对象的表(和Oracle序列)才可以被删除。这是默认行为。

* All Schema Objects - 所有被映射到模型对象的表(和Oracle中用于自动增长列的相应序列)都可以被从模式(schemas)和数据库删除。

* Schema - 整个模式(或数据库被删除。如果模型包含其他模型的对象,那么这些模式(数据库)也会被删除。这个方式仅在 Oracle、MySQL 和 PostgreSQL下可用,在 SQLite 下不行。

数据库创建意味着创建表和表之间的主外键关系。对于 Oracle 数据库来说,如果把主键规定为 DatabaseGeneratedOption.Identity,那么会为这个表创建一个序列和一个插入数据时的触发器,使这个列自动增加。另外,如果选择了模式删除/创建方式,那么将会创建整个模式(数据库)。

数据库核查是否执行检查是否存在于数据库中至少有一个所需的对象。至少有一个表在 MySQL,PostgreSQL 和 SQLite 的存在,以及验证。此外甲骨文,存在的测序实现数据库存在的验证是检查数据库中是否至少有一个要求的对象。而在 MySQL, PostgreSQL, and SQLite 则验证是否至少有一个表。另外,对于 Oracle,还会验证序列是否存在。


默认模式(schema)


目前代码优先(Code-First)实施的行为是,在映射过程中,当创建所有表的名称时,会定义默认的dbo模式名称。因此,Column类会被映射到表 "dbo"."Column"。

这种行为原则上适合SQL Server,但不适合其他类型的数据库。可以通过为每个实体类显式设置模式名称来纠正,使用TableAttribute属性(对fluent映射)或.ToTable()方法。别忘了那些很多彼此关联的EdmMetadata表和中间表,如果在模型中使用了的话。在当前模式/数据库执行的所有操作,允许在表名前不生成数据库模式名。没有标准的方法;然而,从EF提供者实施的水平看,这种解决方法是可以实现的,就像Devart dotConnect。


数据类型


EF支持有限的.NET数据类型,包括signedintegers、Single、Double、Decimal、String、Byte[]、TimeSpan、DateTime、DateTimeOffset、Boolean和Guid。然而,上边所有的.NET 数据类型不能代表所有数据库。


数值(Numeric)类型


不同的数据库用不同的数据类型来表示数值类型。它们中的一些将数值类型有具体分成多种类型。而在Oracle,所有.NET数值类型都存储在NUMBER类型中。这个安排没什么特殊的问题,然而,开发者应该确保数据库数据类型的精度和范围能够足以存储相应的.NET数据类型,反之亦然。理想情况下,类型的范围是相同的。

特别地,EF不支持的.NET无符号整数的映射,因此,MySQL的无符号整数类型必须被映射到一个范围更大的有符号整数上。例如,MySQL的无符号整数被映射到System.Int64,等等。

通过数据优先(Database-First)方法创建一个模型时,一些EF提高者可以自定义规则,将数据库的数值类型映射到.NET类型。而其他EF提供者则是一套固定的规则。一般,Oracle 的EF提供商实现了这个功能。

另外,请记住,Oracle已经没有自动增长的列了。而是,这个列(标识列)作为整数列(如,NUMBER(9)),加上插入记录触发器,基于序列分配一个值给该列。


字符串类型


记住,不同数据库的字符串类型对于可以保存的最大字符串长度有不同的限制,也分成Unicode /非Unicode字符串类型。

最容易发生问题的地方是如何在Oracle中处理空字符串。数据库把空字符串"" 保存为 NULL;这个特性如何?如果这个列有NOT NULL约束,那么就会出现保存问题。如果列为nullable,那么保存操作就没问题。然而,当读取数据,期望,返回null,而不是""。应用程序逻辑必须能够正确地处理这样的特性。

麻烦的另一个来源是不同类型的字符串,或者说Unicode /非Unicode字符串,因为Oracle在这方面有一定限制。在大多数情况下,一个全功能的EF提供者其他方法生成正确的SQL代码。


日期精度


开发人员应注意特定数据库DateTime类型的精度,也就是说,存储秒的小数部分的能力。System.DateTime可以存储小数点后7位的时间值,其精度为100纳秒。一些数据库无法存储这样的精度,精度的不同取决于特定的类型。所以,有时,不截取而保存整个System.DateTime的值,是不可能的。例如:

* Oracle的 DATE 类型存储日期和时间,不存储秒的小数部分,而TIMESTAMP 类型则可以存储,直到纳秒(小数点后9位)。

* MySQL 的DATE 类型,仅仅存储日期,而不存储时间。DATETIME 和 TIMESTAMP 类型存储日期和时间,但 TIMESTAMP 的范围有限,从 1970 到 2038,DATETIME 的范围就比较大了,另外,它们都不存储秒的小数位;秒的小数部分只存储在计算过程中,其只有微秒精度。

* PostgreSQL 的TIMESTAMP 类型存储秒的小数为微妙,小数点后6位。

* SQLite 的 DateTime 类型在数据库被存储为文本,这样,您可能会遇到日期比较问题,通过EF,手动,或是其他工具写入日期数据。


DateTimeOffsett支持


DataTimeOffset 是最有疑问的.NET数据类型。在MS SQLServer 2008、Oracle 和 SQLite中支持,而MS SQL Server 2005、MySQL 或 PostgreSQL则不支持,因为这些数据库没有本地 DateTime 类型,不能存储time zone offset。


并发检查


在SQL Server中,RowVersion / timestamp类型可以被用来方便地实现并发检查。当使用其他数据库时,可以用不同的方法。没有最佳的方法建立并发检查。当然可以为一个实体的所有列设置СoncurrencyMode=Fixed来检查所有值,但是这个选项是最慢的。

通常情况下,我们创建一个UPDATE触发器,把一个值分配给特定并发列。为了进行并发检查,我们可以使用一个 numeric、DateTime 或 Guid (binary) 列:

* DateTime类型是可行的,如果这个数据库数据类型型可以存储足够精度的时间值,以确定它们之间在最小的时间间隔内做出的修改,也就是说,在不到一秒的时间内做出的修改。

* numeric列和当列中的值是递增时的触发器。

* Guid可以用,由服务器端创建。这在大多数现代的DBMS几乎都是可行的。

如果并发检查是一个浮点列,那么要注意精度。

一般在Oracle中,并发检查不能是ORA_ROWSCN pseudo-column,因为这些列的值只有在事务保存后才会改变。


性能


当一个特定数据库的细节没有考虑到,完全有可能,在一个数据库里处理LINQ查询很快,而在另一个数据库却很慢。

通过LINQ方法.Skip()/.Take() 执行数据分页是最消耗资源的操作之一。不同于SQL Server,Oracle中的Skip/Take会产生两个子查询,排序在内层子查询中进行,这可能会负面地影响性能。应该指出,在其他数据库中,分页是完全无效的,特别是,如果排序是在非索引列上进行执行的。

EF提供者的性能和使用SaveChanges()支持批量更新的可用性都会影响保存数据到数据库的过程。

在开发阶段,你需要控制生成用于查询和更新的SQL语句。由于没有内置机制来监测所有生成的SQL,你可以使用第三方工具。当使用Devart EF提供者时,你可以使用免费工具 dbMonitor。如果使用其他EF提供者,你可以在数据库端追踪SQL。

有很多方式来优化LINQ查询:一个LINQ查询可以被重写,可以被分成两个。通过创建存储过程/函数或是视图,把一些操作转移到服务器端的逻辑。可以写和执行本地SQL,而不用ORM功能,通过物化从服务端接受的对象集合,在服务器内存中执行操作等等,把逻辑的一部分,从LINQ to Entities移到LINQ to Objects。

所有EF提供者性能的各个方面信息,参看MSDN Performance Considerations (Entity Framework)


LINQ to Entities 和 EntitySQL: 行为有什么区别?


计算精度


当在数值类型上进行计算或在不同数据库上使用聚合功能时,在相同的初始化下,可能得到的值略有不同。因为不同数据类型的计算精度不同。

通过下边的例子来说明。

表 TEST_TABLE,它的列COLUMN1,Oracle下为 NUMBER(15,10) 或 BINARY_DOUBLE,MySQL下为DOUBLE(15,10) 或 DECIMAL(15,10)。初始化数据:

1.0001

1.0002

1.0003

1.0004

1.0005

1.0006

1.0007

1.0008

1.0009

1.0010

查询

SELECT AVG(COLUMN1) FROM TEST_TABLE

在上边Oracle的两种情况和MySQL DECIMAL(15,10),将返回 1.00055;而在MySQL 5.1 DOUBLE(15,10),将得到1.00055000782013。


查询限制


在EF,开发者可以使用LINQ to Entities或Entity SQL形式化查询,或者两者结合。无论如何,这样一个查询由EF引擎解释成一个表达式树的中间表示,发送到EF提供者来生成SQL。由于EF最初是为SQL Server的开发,因此,有时,EF 提供者为了为特定的目标数据库生成正确的SQL,不得不改变最初的表达式树,然而这并不总是可行的。

最典型的例子是,一个只在Microsoft SQL Server支持的SQL命令CROSS APPLY和OUTER APPLY。因此,在某个情况下(参考 MSDN article 对这种情形的描述),EF通过这些结构转换查询。由于Oracle、MySQL、PostgreSQL和SQLite没有相应的语法结构,不能生成查询,在SQL生成过程中,就会发生错误,

一个带子查询的复杂LINQ查询在SQL Server下会执行,而在Oracle下就不行,参看 existing limitation。通常,当在复杂查询中,使用.Skip()/.Take() 方法时,这个问题就会发生。因为,不像SQL Server,Oracle的实现导致了额外生成的子查询。


Canonical functions


在LINQ to Entities查询中,调用.NET类型的属性和方法会被转换成所谓的EF Canonical Function(参考 MSDNarticle)生成SQL。Canonical functions也可以直接用在Entity SQL。

MSDN的描述如下:

“本节讨论所有的数据提供者都支持的canonical functions,所有的查询技术都使用它。”

这个描述似乎过于乐观,因为不同的DBMS功能不同,有时不能实现所有的功能。

对于DBMS,下面的可能不支持:

* 字符串类型:Reverse

* DateTime类型:AddNanoseconds,AddMicroseconds, AddMilliseconds, CreateDateTimeOffset, CreateTime,CurrentDateTimeOffset, DiffNanoseconds, DiffMilliseconds, DiffMicroseconds, DiffSeconds,DiffMinutes, DiffHours, GetTotalOffsetMinutes

* bitwise 操作:BitWiseNot

* 其他:NewGuid

Microsoft SQL Server 2005/2008、Oracle、MySQL、PostgreSQL 和 SQLite更详细的canonicalfunctions 比较,参考 Entity Framework Canonical Functions


保存改变到数据库


不同EF提供者的实现功能也不同。因此,是否在INSERT / UPDATE / DELETE命令产生字面常量或参数,或是让用户选择一个特定类型的行为,这个问题完全是提供者开发商的责任。

对于向数据库发送NULL值,以及处理DefaultValue,行为同样不一样。在SaveChanges()处理中,批量更新功能的问题没有标准的解决方案。提供者开发商可以随意地自己解决——这就是为什么我推荐,在任何特定情况下,参考特定提供者的文档。Devart dotConnect提供者实现了很多调整DML操作行为的功能,包括批量更新。


结论


本文,我简要描述,一个在为数据库开发EF应用程序的过程中,用户面临的最常见的问题,而不是说Microsoft SQL Server。毫无疑问,许多其他方面没有在文章中天线出来。简言之,我想为开发者提供一些建议。尽管这些建议有点老生常谈,司空见惯,但无论ORM和数据库,遵守它们是明智的。

* Attentively study documentation relatedto the EF-provider of your choice, articles published on the company's blog, aswell as community discussions on appropriate forums.

* Test not only the functionality of yourapplication, but also its performance. Performance tests are also of importancefor ORM solutions. An exceedingly large amount of objects in a model, certainsmart architectural solutions, for instance, table-per-types inheritance (TPT),non-optimal LINQ-queries and a huge number of other factors may lead to acertain decrease in performance.

ef-orm A Simple OR-Mapping framework on multiple databases. 使用手册(中文)http://geequery.github.io/ef-orm/manual/EF-ORM-user-guide.docx  使用示例工程 https://github.com/GeeQuery/ef-orm/tree/master/orm-tutorial EF-ORM是一个轻量,便捷的Java ORM框架。并且具备若干企业级的应用特性,如分库分表、JTA事务等。 代码生成插件for eclipse(请在eclipse中Help/Install new software后输入地址并安装)http://geequery.github.io/plugins/1.3.x/特点一 EF的设计的一个主要目的是提高开发效率,减少编码工作,让开发者“零配置”“少编码”的操作数据库大部分功能。 例如:数据库查询条件的传入问题是所有ORM框架都不能回避的一个问题,所以我经常在想——既然我们可以用向DAO传入一个Entity来实现插入操作,为什么就不能用同样的方法来描述一个不以主键为条件的update/select/delete操作?为什么DAO的接口参数老是变来变去?为什么很多应用中,自行设计开发类来描述各种业务查询条件才能传入DAO?为什么我们不能在数据访问层上花费更少的时间和精力?   JPA1.0和早期的H框架,其思想是将关系型数据库抽象为对象池,这极大的限制了本来非常灵活的SQL语句的发挥空间。而本质上,当我们调用某H框架的session.get、session.load、session.delete时,我们是想传递一个以对象形式表达的数据库操作请求。只不过某H框架要求(并且限制)我们将其视作纯粹的“单个”对象而已。JPA 2.0为了弥补JPA1.0的不足,才将这种Query的思想引入为框架中的另一套查询体系——Criteria API。事实上针对单个对象的get/load/persist/save/update/merge/saveOrUpdate API和Criteria API本来就为一体,只不过是历史的原因被人为割裂成为两套数据库操作API罢了。   因此,对于关系型数据库而言——Entity和Query是一体两面的事物,所谓Query,可以包含各种复杂的查询条件,甚至可以作为一个完整的SQL操作请求的描述。为此,EF彻底将Entity和Query绑在了一起。这种思想,使得—— 开发人员需要编写的类更少。开发人员无需编写其他类来描述复杂的SQL查询条件。也无需编写代码将这些查询条件转换为SQL/HQL/JPQL。DAO层也不会有老要改来改去的接口和API,几乎可以做到零编码。 对单个对象进行CRUD的操作API现在和Criteria API合并在一起。Session对象可以直接提供原本要Criteria API才能提供实现的功能。API大大简化。 IQueryableEntity允许你将一个实体直接变化为一个查询(Query),在很多时候可以用来完成复杂条件下的数据查询。比如 ‘in (?,?,?)’, ‘Between 1 and 10’之类的条件。 xxQL有着拼装语句可读性差、编译器无法检查、变更维护困难等问题,但是却广受开发人员欢迎。这多少有历史原因,也有Criteria API设计上过于复杂的因素。两者一方是极端灵活但维护困难,一方是严谨强大而学习和编写繁琐,两边都是极端。事实上JPA的几种数据查询方式存在青黄不接的问题。选择查询语言xxQL,项目面临后续维护困难,跨数据库移植性差;选择Criteria API,代码臃肿,操作繁琐,很多人望而却步。EF的设计思想是使人早日摆脱拼装SQL/HQL/JPQL的困扰,而是用(更精简易用的)Criteria API来操作数据库。 基于轻量级Criteria API的操作方式,使得对数据库的变更和重构变得非常轻松,解决了SQL语句多对软件维护和移植造成产生的不利影响。 阅读推荐:第3、4章 特点二,将SQL使用发挥到极致,解决SQL拼凑问题、数据库移植问题 大部分OLTP应用系统到最后都不免要使用SQL/JPQL,然而没有一个很好的方法解决SQL多种数据库下兼容性的问题。 EF-ORM中采用了独特的SQL解析和改写技术,能够主动检查并确保SQL语句或者SQL片段在各个数据库上的兼容性。 EF中除了Criteria API以外,可以直接使用SQL语句”或者“SQL片段”。但是这些SQL语句并不是直接传送给JDBC驱动的,而是 有着一个数据库方言层,经过方言层处理的SQL语句,就具备了在当前数据库上正确操作的能力。这相当于提供了一种能跨数据库操作的SQL语言。(E-SQL) E-SQL不但解决了异构数据库的语法问题、函数问题、特殊的写法问题,还解决了动态SQL问题、绑定变量扩展等特性。 对于各种常用SQL函数和运算符,都可以自动转换为当前数据库支持的方言来操作。其函数支持也要多于HQL支持的函数。 阅读推荐:第7、8章 特点三,可能是业界最快的ORM框架. 得益于ASM的动态代码生成技术,部分耗时操作通过动态代码固化为硬编码实现,EF-ORM的大部分操作性能要超过已知的其他框架。 实际性能测试表明,EF的大部分操作都要快于Hiberante和MyBatis, 部分操作速度甚至数十倍于上述框架EF在极限插入模式下,甚至刷新了每秒10万条写入的记录。远远超过了其他框架。 一个初步的性能测试:测试代码:http://geequery.github.io/ef-orm/manual/performance-test.rar 测试报告:http://geequery.github.io/ef-orm/manual/performance-compare.docx 阅读推荐:第9、17章 特点四,分库分表 开发过程中参照了Hibernate Shards、Alibaba TDDL、Cobar等框架,也是基于词法分析器来提取SQL参数,并计算路由。 能支持分库维度含糊等场景下的分库分表。以及包括多库多表下的 order by , distinct, group by, having等操作。 阅读推荐:第10章 特点五,常用DDL操作的封装 从数据库元数据访问,到建表,创建约束,创建sequence等各种DDL操作进行了封装,用户无需编写各种SQL,可以直接通过API操作数据库结构。 尤其是ALTER TABLE等修改数据库的语句,各种不同的RDBMS都有较大语法差异。特点六、解决各种跨RDBMS的移植问题 1、DML操作、自增值处理与返回、查询这些不同数据库操作差异很大的东西,都了统一的封装。 2、DDL操作、建表、删表、trunacte,Sequence创建和TABLE模拟Sequence等,都做了支持。 3、对SQL语法操作和函数的改写与支持。其他特性轻量 该框架对应用环境、连接池、 是否为J2EE应用等没有特殊要求。可以和EJB集成,也可与Spring集成,也可以单独使用。整个框架只有两个JAR包,模块和功能都较为轻量。依赖少 整个框架只有三个jar库。间接依赖仅有commons-lang, slf4j等7个通用库,作为一个ORM框架,对第三方依赖极小。简单直接的API 框架的API设计直接面向数据库操作,不绕弯子,开发者只需要数据库基本知识,不必学习大量新的操作概念即可使用API完成各种DDL/DML操作。 最大限度利用编译器减少编码错误的可能性 API设计和元数据模型(meta-model)的使用,使得常规的数据库查询都可以直接通过Criteria API来完成,无需使用任何JPQL/HQL/SQL。可以让避免用户犯一些语法、拼写等错误。JPA2规范兼容 使用JPA 2.0规范的标准注解方式来定义和操作对象。(但整个ORM不是完整的JPA兼容实现)更高的性能 依赖于ASM等静态字节码技术而不是CGlib,使得改善了代理性能;依赖于动态反射框架,内部数据处理上的开销几乎可以忽略。操作性能接近JDBC水平。对比某H开头的框架,在写入操作上大约领先30%,在大量数据读取上领先50%以上。更多的性能调优手段 debug模式下提供了大量性能日志,帮您分析性能瓶颈所在。同时每个查询都可以针对batch、fetchSize、maxResult、缓存、级联操作类型等进行调整和开关,可以将性能调到最优。可在主流数据库之间任意切换 支持Oracle、MySQL、Postgres、MSSQL、GBase、SQLite、HSQL、Derby等数据库。除了API方式下的操作能兼容各个数据库之外,就连SQL的本地化查询也能使之兼容。JMX动态调节 可以用JMX查看框架运行统计。框架的debug开关和其他参数都可以使用JMX动态调整。动态表支持 表结构元数据的API也向用户开放,同时支持在使用过程中,灵活调整映射关系,因此用户可以用API动态的创建表结构的模型,从而实现各种动态类型和表的映射(例如POJO中包含一个Map,用于映射各种动态扩展的字段)企业级特性支持 SQL分析,性能统计,分库分表,Oracle RAC支持,读写分离支持 标签:eform
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值