使用ORM或纯SQL?

时间:2009-01-30 07:42:18

标签: sql language-agnostic orm

对于我开发的一些应用程序(然后继续忘记),我一直在编写纯SQL,主要用于MySQL。虽然我在SQLAlchemy这样的python中使用过ORM,但我并没有坚持使用它们。通常是文件或复杂性(从我的观点来看)阻碍了我。

我看到它是这样的:使用ORM实现可移植性,使用纯SQL,如果它只是使用一种类型的数据库。在开发需要数据库支持的应用程序时,我真的在寻找何时使用ORM或SQL的建议。

考虑到这一点,使用轻量级包装来处理数据库不一致与使用ORM相比会好得多。

13 个答案:

答案 0 :(得分:235)

作为花费大量时间使用JPA(Java Persistence API,基本上是Java / J2EE / EJB的标准化ORM API)的人,包括Hibernate,EclipseLink,Toplink,OpenJPA等,我将分享我的一些观察。

  1. ORM并不快。它们可以是足够的,并且大部分时间都足够好但是在高容量低延迟环境中它们是禁止的;
  2. 在Java和C#等通用编程语言中,需要大量的魔力才能使它们工作(例如,在Java,仪器等中加载时编织);
  3. 当使用ORM时,而不是从SQL(这似乎是意图)更进一步,你会惊讶于你花了多少时间调整XML和/或注释/属性来让你的ORM生成高性能的SQL;
  4. 对于复杂的查询,确实没有替代品。就像在JPA中一样,有些查询在原始SQL中是不可能的,当你必须在JPA中使用原始SQL时,它并不漂亮(C#/ .Net至少有动态类型 - var - 这很多比Object数组好;)
  5. 使用ORM时有很多“陷阱”。这包括意外或意外的行为,您必须构建对数据库执行SQL更新的功能(通过在JPA或类似方法中使用refresh(),因为JPA默认会缓存所有内容,因此它不会捕获直接数据库更新 - 运行直接SQL更新是一种常见的生产支持活动);
  6. 对象关系不匹配总会导致问题。对于任何这样的问题,在抽象的复杂性和完整性之间存在权衡。有时候我觉得JPA走得太远了,并且达到了一个收益递减的真正规律,其中复杂性不受抽象的影响。
  7. 还有一个问题需要更多解释。

    Web应用程序的传统模型是具有持久层和表示层(可能在其间具有服务或其他层,但这些是本讨论的重要部分)。 ORM强制从持久层到表示层(即您的实体)的刚性视图。

    对更多原始SQL方法的批评之一是,您最终会得到所有这些仅由一个查询使用的VO(值对象)或DTO(数据传输对象)。这被吹捧为ORM的优势,因为你摆脱了它。

    那些问题不会随着ORM而消失,它们只是移动到表示层。您可以创建自定义表示对象,而不是为查询创建VO / DTO,通常每个视图对应一个。这怎么样更好?恕我直言,不是。

    我在ORM or SQL: Are we there yet?写了这篇文章。

    我最近选择的持久性技术(Java)是ibatis。它是一个非常薄的SQL包装器,可以完成JPA 90%以上的功能(它甚至可以对关系进行延迟加载,尽管没有详细记录)但是开销(在复杂性和实际代码方面)要少得多。 / p> 去年在我写的GWT应用程序中出现了这个问题。从EclipseLink到服务实现中的表示对象的大量翻译。如果我们使用ibatis,那么使用ibatis创建适当的对象然后将它们一直传递到堆栈中会更加简单。一些纯粹主义者可能认为这是Bad™。也许是这样(理论上),但我告诉你:它会导致更简单的代码,更简单的堆栈和更高的生产力。

答案 1 :(得分:155)

ORM有一些不错的功能。他们可以处理将数据库列复制到对象字段的大部分工作。它们通常处理将语言的日期和时间类型转换为适当的数据库类型。它们通常通过实例化嵌套对象来非常优雅地处理一对多关系。我发现如果你设计数据库时考虑到ORM的优点和缺点,它可以节省大量数据进出数据库的工作量。 (如果你需要映射那些,你会想知道它如何处理多态和多对多关系。正是这两个域提供了大部分“阻抗不匹配”,这使得某些人称ORM为“计算机科学的越南” 。)

对于事务性的应用程序,即你发出请求,获取一些对象,遍历它们以获取一些数据并在网页上呈现它,性能税很小,并且在很多情况下ORM可以更快,因为它会它之前看到的缓存对象,否则会多次查询数据库。

对于报告繁重的应用程序,或者每个请求处理大量数据库行的应用程序,ORM税会更加重,并且它们执行的缓存会变成一个巨大的,无用的内存占用负担。在这种情况下,简单的SQL映射(LinQ或iBatis)或精简DAL中的手工编码SQL查询是可行的方法。

我发现任何大型应用程序都会让你自己使用这两种方法。 (ORM用于直接的CRUD和SQL /瘦DAL用于报告)。

答案 2 :(得分:40)

我说 R eads的纯SQL, CUD 的ORM。

性能是我一直关注的,特别是在Web应用程序中,还有代码可维护性和可读性。为了解决这些问题,我写了SqlBuilder

答案 3 :(得分:14)

ORM不仅仅是可移植性(即使使用ORM,也很难实现)。当ORM工具将您从编写样板SQL查询(通过PK或谓词,插入,更新和删除选择)中解放出来时,它为您提供的基本上是持久存储的抽象层,让您专注于问题域。 / p>

答案 4 :(得分:10)

任何可敬的设计都需要对数据库进行一些抽象,只是为了处理阻抗不匹配。但最简单的第一步(并且适用于大多数情况)我预计会是DAL,而不是重量级ORM。您唯一的选择不是频谱的末端。


编辑回应评论,要求我描述我如何区分DAL和ORM:

DAL是你自己编写的,可能从一个简单封装表并将其字段映射到属性的类开始。 ORM是您不编写的代码或从dbms架构的其他属性推断出的抽象机制,主要是PK和FK。 (这是你发现自动抽象是否开始泄漏的地方。我更愿意故意告知他们,但这可能只是我个人的偏好。)

答案 5 :(得分:7)

每个工具都有其目的和愿景。我已经创建http://www.jooq.org/完全符合您的需求,尽管iBatis也可能是一个很好的解决方案。

jOOQ具有基本的ORM功能,但它主要关注我认为大多数开发人员最需要的东西,当他们试图找到满足他们需求的最佳ORM时:

  • 代码生成
  • 变量绑定(这是JDBC的痛苦)
  • SQL语法抽象(防止语法错误)

但是它们往往走得太远而且提供了如此多的抽象,你不会认为它们是在运行RDBMS。另一方面,您选择RDBMS正是因为

  • 它是一个强大的数据源
  • SQL可以做很多好的,高性能的事情(嵌套选择,联合,复杂连接等)。 ORM通常不能做这些事情。
  • 您可以自己处理交易和会话
  • 您有UDT和存储过程

jOOQ正好解决了这些问题。它的表现与JDBC一样好,但没有痛苦。

答案 6 :(得分:6)

使我的ORM使用真正飞行的关键是代码生成。我同意ORM路由在代码性能方面不是最快的。但是当你拥有一个中型到大型团队时,数据库正在迅速改变从数据库重新生成类和映射的能力,因为构建过程的一部分是值得注意的,特别是当你使用CI时。所以你的代码可能不是最快的,但你的编码将是 - 我知道我会在大多数项目中采用哪些代码。

我的建议是在Schema仍然流畅的情况下使用ORM进行开发,使用分析来查找瓶颈,然后使用原始Sql调整需要它的区域。

另一个想法是,如果以正确的方式使用,Hibernate中内置的缓存通常可以大幅提升性能。不再需要返回DB来读取参考数据。

答案 7 :(得分:5)

在现代软件开发场景中,是否使用框架的困境是很常见的。

重要的是要理解每个框架或方法都有其优点和缺点 - 例如根据我们的经验,我们发现ORM在处理事务时非常有用,即插入/更新/删除操作 - 但是当涉及到提取时如果数据结果复杂,评估ORM工具的性能和效果就变得非常重要。

同样重要的是要理解,选择框架或方法并实施其中的所有内容并非强制性。我们的意思是我们可以混合使用ORM和本机查询语言。许多ORM框架为本机SQL中的插件提供扩展点。我们应该尽量不要过度使用框架或方法。我们可以结合某些框架或方法,并提供适当的解决方案。

在插入,更新,删除,具有高并发性的版本控制时,您可以使用ORM,并且可以使用Native SQL生成报告和长列表

答案 8 :(得分:4)

没有'一刀切“的解决方案,对于'我应该使用或者是否应该使用?'这个问题也是如此? ”。

我会说:如果你必须编写一个非常“数据”的应用程序/工具,没有太多其他逻辑,那么我将使用纯SQL,因为SQL是这种应用程序的特定于域的语言

另一方面,如果我要编写一个包含大量“域”逻辑的业务/企业应用程序,那么我会编写一个可以用代码表达这个域的丰富类模型。在这种情况下,OR / M映射器可能非常有助于成功执行此操作,因为它需要大量的管道代码。

答案 9 :(得分:2)

我知道这个问题很老了,但我想我会发一个答案,万一有人像我一样遇到它。 ORM已经走过了漫长的道路。其中一些实际上为您提供了两全其美的优势:提高开发效率并保持性能。

查看SQL数据(http://sqldata.codeplex.com)。对于涵盖所有碱基的c#,它是一种非常轻的ORM。

仅供参考,我是SQL Data的作者。

答案 10 :(得分:1)

我开发的一个应用程序是用python编写的IRC机器人。它使用的模块在不同的线程中运行,但是在使用sqlite时我还没有找到一种处理线程的方法。但是,对于一个单独的问题,这可能会更好。

我真的应该重新编写标题实际问题。我以前从未用任何语言实际使用过DAL。

答案 11 :(得分:1)

使用 SQL的ORM,但提供编译时检查和类型安全性。就像我最喜欢的:Data Knowledge Objects(披露:我写的)

例如:

for (Bug bug : Bug.ALL.limit(100)) {
  int id = bug.getId();
  String title = bug.getTitle();
  System.out.println(id +" "+ title);
}

全流媒体。易于设置(无需定义映射 - 读取现有模式)。支持连接,事务,内部查询,聚合等。您可以在SQL中执行任何操作。并且已经从巨型数据集(金融时间序列)一直到普通(Android)证明。

答案 12 :(得分:1)

我想把声音添加到回复的合唱中,说“有中间地带!”。

对于应用程序程序员来说,SQL是您可能想要控制的事物以及您几乎肯定不想被控制的事情的混合物。

我一直想要的是一个层(称之为DAL,ORM或micro-ORM,我不介意哪个),它将负责完全可预测的决策(如何拼写SQL关键字,括号中的位置) go,何时发明列别名,为包含两个浮点数和一个int ...的类创建的列,同时让我负责SQL的更高级别方面,即如何安排JOIN,服务器 - 边计算,DISTINCT,GROUP BY,标量子查询等

所以我写了一些这样做:http://quince-lib.com/

这是针对C ++的:我不知道这是否是你正在使用的语言,但同样有趣的是看到这对于“中间地带”看起来是什么样的。