2009-10-16 44 views

回答

13

复杂性。

ORM如果您的应用程序是域驱动的,并且对象之间的关系很复杂,或者您需要让此对象定义应用程序的功能。

JDBC/SQL如果你的应用是很简单的,只是目前他们之间直接从数据库或数据的关系是很简单的。

该书由Martin Fowler“企业应用架构模式”解释这两种类型之间的差异要好得多:

见:Domain ModelTransaction Script

+1

+1。我自己的方式是,您必须了解ORM的大量不变成本“为自己付出”的感觉。 – 2009-10-16 00:26:06

+0

我必须同意这一点 - 但我还想补充说,有时候在单个应用程序中使用这两种方法是有道理的。 – 2009-11-11 11:31:52

+0

...如果你的应用程序太复杂以至于ORM是合理的,架构师应该真的质疑是否有更好的方法来分解应用程序(提示:微服务)。 – 2017-08-16 04:46:18

1

这也取决于学习曲线上。

Ebean ORM如果您满意地使用JPA批注进行映射(@Entity,@Table,@OneToMany等),它的学习曲线很低(简单的API,简单的查询语言)。

9

JDBC

  1. 随着JDBC,开发者必须写代码到对象模型的数据表示映射到关系数据模型和其相应的数据库架构。
  2. 使用JDBC,Java对象与数据库表的自动映射以及反向转换将由开发人员用代码行手动处理。
  3. JDBC仅支持本机结构化查询语言(SQL)。开发人员必须找出访问数据库的有效方法,即从多个查询中选择有效的查询来执行相同的任务。
  4. 使用JDBC处理大量数据库特定代码的持久数据(数据库表)的应用程序。写入映射表数据到应用程序对象的代码反之亦然实际上是将表字段映射到对象属性。当表更改或数据库更改时,必须更改对象结构以及更改写入映射表到对象/对象到表的代码。
  5. 使用JDBC,开发人员负责处理JDBC结果集,并通过代码将其转换为Java对象以在应用程序中使用此持久数据。所以对于JDBC,Java对象和数据库表之间的映射是手动完成的。
  6. 使用JDBC,通过手动编码来维护高速缓存。
  7. 在JDBC中,并不检查每个用户是否更新过数据。这项检查必须由开发者添加。

HIBERNATE。

  1. Hibernate是一个灵活而强大的ORM解决方案,可将Java类映射到数据库表。 Hibernate自己负责使用XML文件进行映射,因此开发人员无需为此编写代码。
  2. Hibernate提供了透明持久性,开发人员在与RDBMS交互期间不需要显式地将数据库表元组映射到应用程序对象。
  3. Hibernate提供了一种功能强大的查询语言Hibernate查询语言(独立于数据库类型),用熟悉的SQL语法表达并包含对多态查询的全面支持。 Hibernate也支持原生SQL语句。它还选择一种有效的方法来为应用程序执行数据库操作任务。
  4. Hibernate自己提供了这个映射。表和应用程序对象之间的实际映射在XML文件中完成。如果数据库或任何表中有更改,则只需更改XML文件属性。
  5. Hibernate通过维护对象 - 表映射本身来减少代码行,并以Java对象的形式将结果返回给应用程序。它减轻了程序员手动处理持久数据的难度,从而缩短了开发时间和维护成本。
  6. 将Hibernate与透明持久性缓存设置为应用程序工作空间。作为查询的结果,关系元组被移动到这个缓存中。如果客户端应用程序在相同的写入操作中多次读取相同的数据,它会提高性能自动透明持久性允许开发人员更专注于业务逻辑而不是此应用程序代码。
  7. 由于这个定义的字段,Hibernate使开发人员能够定义版本类型字段到应用程序。每当关系元组以Java对象的形式更新到该表时,Hibernate都会更新数据库表的版本字段。因此,如果两个用户检索相同的元组,然后修改它,并且一个用户将此修改的元组保存到数据库,则Hibernate会自动更新此元组的版本。当其他用户尝试将更新的元组保存到数据库时,它不允许保存它,因为此用户没有更新的数据。
1

我想你忘了看“功能关系映射”

我会总结说:

  • 如果你想专注于数据结构,使用像一个ORM JPA/Hibernate
  • 如果您想阐明治疗方法,请查看FRM库:QueryDSL或Jooq
  • 如果您需要将SQL请求调整到特定数据库,请使用JDBC和本机SQL请求

各种“关系映射”技术的优势在于可移植性:确保您的应用程序可以在大多数ACID数据库上运行。 否则,当您手动写入SQL请求时,您将处理各种SQL方言之间的差异。

当然,你可以克制自己SQL92标准(然后做一些函数式编程),或者你可以重用functionnal编程的一些概念与ORM框架

的ORM strenghs建在一个会话对象,它可以充当作为瓶颈:

  1. 只要底层数据库事务正在运行,它就管理对象的生命周期。
  2. 它在Java对象和数据库行之间保持一对一映射(并使用内部缓存来避免重复的对象)。
  3. 它自动检测关联更新和孤儿对象删除
  4. 它处理乐观或悲观锁定的并发问题。

尽管如此,它的优势也是它的弱点:

  1. 会话必须能够所以你需要工具来比较的对象等于/ hashCode方法 但对象平等必须在“业务键根植“而不是数据库ID(新的瞬态对象没有数据库ID!)。 但是,一些具体化的概念没有业务平等(例如操作)。 常见的解决方法依赖于倾向于打乱数据库管理员的GUID。

  2. 会话必须侦测关系更改,但其映射规则会推动使用不适合于业务算法的集合。 有时候你想要使用HashMap,但是ORM将要求密钥是另一个“富域对象”而不是另一个“轻量级对象”...... 然后,您必须在作为密钥的丰富域对象上实现对象相等。 .. 但是,你不能因为这个对象在商业世界中没有对应。 所以你回到一个简单的列表,你必须迭代(和性能问题的结果)

  3. ORM API有时不适合现实世界的使用。 例如,当您获取数据时,真实世界的Web应用程序尝试通过添加一些“WHERE”子句来强制执行会话隔离...然后,“Session.get(id)”不够用,您需要转向更复杂DSL(HSQL,Criteria API)或返回到本机SQL数据库对象与专用于其他框架的其他对象(如OXM框架=对象/ XML映射)相冲突。 例如,如果您的REST服务使用jackson库来序列化业务对象。但是这个杰克逊恰好映射到一个Hibernate One。 则要么合并两个和你的API和数据库之间的强耦合出现 或者您必须实现一个翻译,所有你从ORM保存代码丢失那里......

在另一边FRM是“对象关系映射”(ORM)和原生SQL查询(使用JDBC)之间的一种折衷方案。解释FRM和ORM之间差异的最佳方法是采用DDD方法。

  • 对象关系映射授权使用“富域对象”,这是Java类,其状态是数据库事务
  • 功能关系映射依靠这是不可改变的“可怜的域对象”(以至于在可变的你必须在每次你想改变它的内容的时候克隆一个新的)

它释放了ORM会话上的约束,并且依赖于SQL上的大部分时间在DSL上(因此可移植性无关紧要) 但另一方面,您必须查看交易细节,concurrenc y问题

List persons = queryFactory。select(from) 。( person.firstName.eq(“John”), person.lastName.eq(“Doe”)) .fetch();