使用ORM或纯SQL?

对于我开发的一些应用程序(后来忘记了),我一直在编写纯SQL,主要针对MySQL。 虽然我已经在Python中像SQLAlchemy一样使用了ORM,但是我并没有坚持太久。 通常这是文件或复杂性(从我的观点来看)阻止我回来。

我看到它是这样的:使用一个ORM的便携性,普通的SQL,如果它只是要使用一种types的数据库。 在开发需要数据库支持的应用程序时,我确实在寻找何时使用ORM或SQL的build议。

考虑一下,使用一个轻量级的包装来处理数据库不一致与使用一个ORM将会好得多。

ORM有一些很好的function。 他们可以处理很多将数据库列复制到对象字段的工作。 他们通常会将语言的date和时间types转换为适当的数据库types。 它们通常可以通过实例化嵌套对象来优雅地处理一对多的关系。 我发现如果你在devise数据库时考虑到了ORM的长处和短处,那么在从数据库中获取数据的过程中可以节省大量的工作。 (如果你需要映射这些关系,你会想知道它是如何处理多态和多对多的关系的,这两个域提供了大部分“阻抗不匹配”,使一些ORM成为“计算机科学的越南” 。)

对于事务性的应用程序来说,例如你发出一个请求,得到一些对象,遍历它们来获取一些数据并把它显示在网页上,性能税很小,在很多情况下,ORM可以更快,因为它会caching对象以前看过,否则会多次查询数据库。

对于报表繁重的应用程序,或者每个请求处理大量数据库行的应用程序,ORM税收要重得多,而且他们所做的caching变成了一个巨大的,无用的内存负担。 在这种情况下,简单的SQL映射(LinQ或iBatis)或手动编码的SQL查询在精简的DAL中是一种可行的方法。

我发现任何大规模的应用程序,你会发现自己使用这两种方法。 (用于报告的简单的CRUD和SQL /精简DAL的ORM)。

作为一个花了很长时间处理JPA(Java Persistence API,基本上是Java / J2EE / EJB的标准ORM API)的人,包括Hibernate,EclipseLink,Toplink,OpenJPA和其他人,我会分享一些我的观察结果。

  1. ORMs不是很快。 它们可以是足够的,大部分时间足够好,但是在大容量低延迟的环境中,它们是不可能的。
  2. 在像Java和C#这样的通用编程语言中,你需要很多魔法来使它们工作(例如,加载时间在Java中的编织,工具等)。
  3. 当使用一个ORM,而不是从SQL进一步(这似乎是意图),你会惊讶你花了多less时间来调整XML和/或注释/属性让你的ORM生成性能的SQL;
  4. 对于复杂的查询,确实没有替代品。 就像在JPA中,有一些查询是不可能的,在原始SQL中,当你必须在JPA中使用原始SQL时,它不是很漂亮(C#/ .Net至less有dynamictypes – var – 这是很多比对象数组更好);
  5. 使用ORM时有很多“陷阱”。 这包括意外或意外的行为,因为必须构build对数据库执行SQL更新的能力(通过在JPA或类似方法中使用refresh(),因为默认情况下,JPAcaching所有内容,因此不会捕获直接数据库更新 – 运行直接SQL更新是一个常见的生产支持活动);
  6. 对象 – 关系不匹配总是会导致问题。 有了这样的问题,在抽象的复杂性和完整性之间就会有一个折衷。 有时候我觉得JPA太过分了,并且遇到了一个真正的收益递减规律,那就是复杂性并没有被抽象的理由所certificate。

还有一个问题需要更多的解释。

Web应用程序的传统模型是拥有一个持久层和一个表示层(可能有一个服务层或其他层,但这些对于这个讨论来说是重要的两个层)。 ORM强制从持久层直到表示层(即你的实体)的严格看法。

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

事情是这些问题不会与ORM消失,他们只是上升到表示层。 您可以创build自定义的演示文稿对象,而不是为查询创buildVO / DTO,通常为每个视图创build一个。 这是如何更好? 恕我直言,这不是。

我已经用ORM或SQL写了这个:我们在那里吗? 。

我最近selectJava的持久性技术是ibatis。 这是一个非常简单的SQL封装,它可以完成JPA可以做90%以上的工作(它甚至可以做关系的延迟加载,虽然没有很好的文档),但是在复杂性和实际代码方面开销less得多。

去年,我在写一个GWT应用程序。 从EclipseLink到服务实现中的表示对象有许多翻译。 如果我们使用ibatis,那么使用ibatis创build适当的对象,然后将它们一直传递到堆栈上会非常简单。 一些纯粹主义者可能会认为这是坏的。 也许这样(理论上),但我告诉你:它会导致更简单的代码,更简单的堆栈和更高的生产力。

我说普通SQL读取,ORM的CUD。

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

ORM不仅仅是可移植性(就这一点而言,即使使用ORM也很难实现)。 它提供的基本上是一个永久存储层的抽象层,当一个ORM工具使你免于编写模板SQL查询(通过PKselect或谓词,插入,更新和删除),并让你专注于问题领域。

任何可敬的devise都需要对数据库进行一些抽象,以处理阻抗不匹配问题。 但是,最简单的第一步(对于大多数情况来说足够了),我预计会是DAL,而不是重量级的ORM。 你唯一的select不是那些在光谱的末端。


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

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

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

我的build议是在Schema仍然stream畅时使用ORM进行开发,使用分析来查找瓶颈,然后使用原始Sql调整那些需要它的区域。

另一个想法是,如果以正确的方式使用Hibernate中的caching,通常可以大大提高性能。 没有更多的回到数据库来读取参考数据。

每个工具都有其目的和愿景。 我创build了http://www.jooq.org/完全适合您的需求,尽pipeiBatis也可能是您的一个很好的解决scheme。;

jOOQ具有基本的ORM特性,但是它主要关注的是大多数开发人员最需要的东西,当试图根据需要find最好的ORM时:

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

但是,他们往往过分,并提供如此多的抽象,你不会认为他们对RDBMS运行。 另一方面,你select了一个RDBMS正是因为

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

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

在现代软件开发场景中,是否使用框架的困境是相当普遍的。

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

另外重要的是要明白,select一个框架或一种方法并且不是强制性的, 我们的意思是我们可以混合使用ORM和原生查询语言。 许多ORM框架给原生SQL插件提供了扩展点。 我们应该尽量不要过度使用框架或方法。 我们可以结合某些框架或方法,并提出一个适当的解决scheme。

当涉及到插入,更新,删除,高级并发的版本控制时,您可以使用ORM,您可以使用Native SQL进行报告生成和长列表

没有“一刀切”的解决scheme,对于“我应该使用or还是不是? ”。

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

另一方面,如果我要编写一个包含大量“域”逻辑的商业/企业应用程序,那么我会编写一个可以在代码中表示该域的丰富类模型。 在这种情况下,一个OR / M映射器可能会非常有帮助,因为它需要大量的pipe道代码。

我知道这个问题已经很老了,但是我认为如果有人像我一样遇到这个问题,我会发表一个答案。 ORM已经走过了很长的一段路。 其中一些实际上给你两全其美:发展提高生产力和保持业绩。

看看SQL数据( http://sqldata.codeplex.com )。 这是一个非常轻的ORM为C#涵盖所有的基地。

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

我开发的应用程序之一是用python编写的IRC bot。 它使用的模块在单独的线程中运行,但是我还没有想出使用sqlite时处理线程的方法。 不过,对于另外一个问题,这可能会更好。

我真的应该只是重新标题实际问题。 我以前从来没有用过任何语言的DAL。

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

例如:

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

完全stream媒体。 易于设置(无需定义映射 – 读取您现有的模式)。 支持连接,事务,内部查询,聚集等。几乎所有你可以在SQL中做的事情。 并已经从巨大的数据集(金融时间序列)一直到微不足道的(Android)。

我想把我的声音添加到“有一个中间地带!”的答复合唱中。

对于应用程序员来说,SQL是你可能想要控制的东西的混合物,而你几乎肯定不想被控制的东西。

我一直想要的是一个层(称之为DAL,ORM或微ORM,我不介意哪一个)负责完全可预测的决定(如何拼写SQL关键字,括号的位置,发明列别名,为一个拥有两个浮点数和一个int的类创build什么列…),同时让我负责SQL的更高层次的方面,即如何安排JOIN,服务器端计算, DISTINCT,GROUP BY,标量子查询等

所以我写了这样的: http : //quince-lib.com/

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