对于我开发的一些应用程序(后来渐渐忘记了),我一直在编写纯SQL,主要用于MySQL。虽然我在python中使用过orm,比如SQLAlchemy,但我并没有坚持使用它们太久。通常是文档或复杂性(从我的角度来看)阻碍了我。

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

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


任何值得尊敬的设计都需要对数据库进行一些抽象,以处理阻抗不匹配。但是我认为最简单的第一步(对于大多数情况来说已经足够了)应该是DAL,而不是重量级的ORM。你唯一的选择并不是那些极端的选择。


编辑回复一个要求我描述如何区分DAL和ORM的评论:

DAL是您自己编写的,可能从简单地封装一个表并将其字段映射到属性的类开始。ORM是不需要为从dbms模式的其他属性推断出的抽象机制而编写的代码,主要是pk和fk。(这是您发现自动抽象是否开始出现漏洞的地方。我更喜欢有意地告知他们,但这可能只是我的个人偏好)。

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

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

我真的应该把题目和问题都改写一下。我从来没有在任何语言中使用过DAL。

作为一个经常使用JPA (Java Persistence API,基本上是Java/J2EE/EJB的标准化ORM API)(包括Hibernate、EclipseLink、Toplink、OpenJPA等)的人,我将分享一些我的观察结果。

ORMs are not fast. They can be adequate and most of the time adequate is OK but in a high-volume low-latency environment they're a no-no; In general purpose programming languages like Java and C# you need an awful lot of magic to make them work (eg load-time weaving in Java, instrumentation, etc); When using an ORM, rather than getting further from SQL (which seems to be the intent), you'll be amazed how much time you spend tweaking XML and/or annotations/attributes to get your ORM to generate performant SQL; For complex queries, there really is no substitute. Like in JPA there are some queries that simply aren't possible that are in raw SQL and when you have to use raw SQL in JPA it's not pretty (C#/.Net at least has dynamic types--var--which is a lot nicer than an Object array); There are an awful lot of "gotchas" when using ORMs. This includes unintended or unexpected behavior, the fact that you have to build in the capability to do SQL updates to your database (by using refresh() in JPA or similar methods because JPA by default caches everything so it won't catch a direct database update--running direct SQL updates is a common production support activity); The object-relational mismatch is always going to cause problems. With any such problem there is a tradeoff between complexity and completeness of the abstraction. At times I felt JPA went too far and hit a real law of diminishing returns where the complexity hit wasn't justified by the abstraction.

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

Web应用程序的传统模型是有一个持久层和一个表示层(中间可能有一个服务或其他层,但这是本文中重要的两个层)。orm强制从持久层到表示层(即实体)使用刚性视图。

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

问题是,这些问题不会随着orm而消失,它们只会上升到表示层。不为查询创建VOs/ dto,而是创建自定义表示对象,通常为每个视图创建一个。这怎么更好呢?恕我直言,它不是。

我已经用ORM或SQL写过了:我们做到了吗?

最近我选择的持久化技术(在Java中)是ibatis。它是一个非常薄的SQL包装器,可以完成JPA所能做的90%以上的工作(它甚至可以进行惰性加载关系,尽管它没有良好的文档),但开销要小得多(就复杂性和实际代码而言)。

这是在去年我编写的GWT应用程序中出现的。在服务实现中,从EclipseLink到表示对象的大量转换。如果我们使用ibatis,那么用ibatis创建适当的对象,然后在堆栈中上下传递它们就会简单得多。一些纯粹主义者可能会认为这是坏的™。也许是这样(理论上),但我告诉你:它会带来更简单的代码、更简单的堆栈和更高的生产力。

ORMs have some nice features. They can handle much of the dog-work of copying database columns to object fields. They usually handle converting the language's date and time types to the appropriate database type. They generally handle one-to-many relationships pretty elegantly as well by instantiating nested objects. I've found if you design your database with the strengths and weaknesses of the ORM in mind, it saves a lot of work in getting data in and out of the database. (You'll want to know how it handles polymorphism and many-to-many relationships if you need to map those. It's these two domains that provide most of the 'impedance mismatch' that makes some call ORM the 'vietnam of computer science'.)

对于事务性应用程序,即您发出请求,获取一些对象,遍历它们以获得一些数据并在Web页面上呈现,性能损失很小,并且在许多情况下ORM可以更快,因为它将缓存以前见过的对象,否则将多次查询数据库。

对于报告量大的应用程序,或者每个请求都要处理大量的数据库行,ORM税要重得多,它们所做的缓存变成了一个巨大的、无用的内存占用负担。在这种情况下,可以使用简单的SQL映射(LinQ或iBatis)或在瘦DAL中手工编写SQL查询。

我发现,对于任何大型应用程序,您都会发现自己同时使用这两种方法。(ORM用于直接的CRUD, SQL/thin DAL用于报告)。

在现代软件开发场景中,是否使用框架是非常常见的难题。

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

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

当涉及到高并发性的插入、更新、删除和版本控制时,可以使用ORM,还可以使用Native SQL生成报告和长清单

使我的ORM使用真正成功的关键是代码生成。就代码性能而言,我同意ORM路由不是最快的。但是,当您拥有一个中型到大型的团队时,DB正在迅速变化,从DB中重新生成类和映射作为构建过程的一部分的能力是值得注意的,特别是当您使用CI时。所以你的代码可能不是最快的,但你的代码会-我知道我在大多数项目中会采用哪种。

我的建议是在模式仍处于流动状态时使用ORM进行开发,使用分析来发现瓶颈,然后使用原始Sql优化那些需要它的区域。

另一个想法是,如果使用得当,Hibernate内建的缓存通常可以大大提高性能。不再需要返回DB读取引用数据。

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

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

另一方面,如果我要编写一个包含大量“领域”逻辑的业务/企业应用程序,那么我将编写一个富类模型,它可以在代码中表达这个领域。在这种情况下,OR/M映射器可能会非常有用,因为它可以从您手中省去大量管道代码。

我用纯SQL表示读取,用ORM表示CUD。

性能是我一直关注的问题,尤其是在web应用程序中,但同时也关注代码的可维护性和可读性。为了解决这些问题,我编写了SqlBuilder。

使用像SQL一样工作的ORM,但提供编译时检查和类型安全。比如我最喜欢的:数据知识对象(披露:是我写的)

例如:

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

完全流。易于设置(不需要定义映射-读取现有模式)。支持连接、事务、内部查询、聚合等。几乎可以用SQL做任何事情。从庞大的数据集(金融时间序列)一直到琐碎的数据集(Android),这一点都得到了证明。

我知道这个问题很老了,但我想我应该在这里发布一个答案,以防有人像我一样遇到这个问题。orm已经走过了很长的路。其中一些实际上为您提供了两全其美的服务:提高开发效率并保持性能。

看看SQL Data (http://sqldata.codeplex.com)。它是c#的一个轻量级ORM,涵盖了所有基础。

供参考,我是SQL数据的作者。

我想和大家一起回答:“我们有一个中间立场!”

对于应用程序程序员来说,SQL是您可能想要控制的东西和您几乎肯定不想费心控制的东西的混合体。

我一直想要的是一个层(称之为DAL、ORM或microorm,我不介意哪个),它将负责完全可预测的决策(如何拼写SQL关键字,括号放在哪里,何时创建列别名,为一个包含两个浮点数和一个int的类创建哪些列……),同时让我负责SQL的高级方面,即如何安排join、服务器端计算、DISTINCTs、GROUP by、标量子查询等。

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

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