对于我开发的一些应用程序(然后就忘记了),我一直在编写纯SQL,主要针对MySQL。虽然我已经使用过像SQLAlchemy这样的Python ORM,但我并没有长期坚持使用它们。通常是文档或者复杂性(从我的角度来看)让我望而却步。
我认为:如果只使用一种类型的数据库,可以使用纯SQL,如果需要可移植性,则使用ORM。我真的想寻求关于在开发需要数据库支持的应用程序时何时使用ORM或SQL的建议。
思考一下,与使用ORM相比,仅使用轻量级包装器来处理数据库不一致会更好。
对于我开发的一些应用程序(然后就忘记了),我一直在编写纯SQL,主要针对MySQL。虽然我已经使用过像SQLAlchemy这样的Python ORM,但我并没有长期坚持使用它们。通常是文档或者复杂性(从我的角度来看)让我望而却步。
我认为:如果只使用一种类型的数据库,可以使用纯SQL,如果需要可移植性,则使用ORM。我真的想寻求关于在开发需要数据库支持的应用程序时何时使用ORM或SQL的建议。
思考一下,与使用ORM相比,仅使用轻量级包装器来处理数据库不一致会更好。
作为一个曾经花费很多时间工作于JPA(Java Persistence API,基本上是Java/J2EE/EJB的标准ORM API),包括Hibernate、EclipseLink、Toplink、OpenJPA等,我想分享一些自己的观察。
还有一个需要更详细解释的问题。
Web应用程序的传统模型是具有持久层和表示层(可能有服务或其他层位于其中,但这些对本讨论非常重要)。ORM强制从持久层向上到表示层(即你的实体)看待问题。
更原始的 SQL 方法之一的批评是,你最终会有很多仅用于一个查询的 VOs(值对象)或 DTOs(数据传输对象)。ORM 的优点在于消除了这些问题。
但实际上,这些问题并没有随着 ORM 而消失,而是转移到了表示层。你需要为每个视图创建自定义表示对象,通常为每个视图创建一个。这比创建查询的 VOs/DTOs 好在哪里呢?在我看来并没有什么好处。
我在ORM 或 SQL:我们到达了哪里?中对此进行了讨论。
我现在(在 Java 中)选择的持久化技术是 ibatis。它是一个相当轻量级的 SQL 包装器,可以完成 JPA 的 90%+ 功能(甚至可以进行关系的懒加载,尽管文档记录不太清楚),但开销要少得多(包括复杂性和实际代码方面)。
去年我写 GWT 应用程序时遇到了这个问题。在服务实现中从 EclipseLink 转换为表示对象非常麻烦。如果我们使用 ibatis,创建适当的对象然后将它们传递上下整个堆栈会更加简单。有些纯粹主义者可能会认为这是不好的™。也许是(从理论上来说),但我告诉你:这将导致更简单的代码、更简单的堆栈和更高的生产力。
对于事务性应用程序,即您发送请求、获取一些对象、遍历这些对象以获取一些数据并在Web页面上呈现它们的情况下,性能损失很小,而且在许多情况下,ORM可能会更快,因为它会缓存它之前见过的对象,否则将多次查询数据库。
对于报表密集型或每个请求处理大量数据库行的应用程序,ORM的负担要重得多,并且它们做的缓存会变成一个庞大而无用的内存负担。在这种情况下,简单的SQL映射(LinQ或iBatis)或在薄的数据访问层中手动编写SQL查询是正确的选择。
我发现,对于任何大型应用程序,您会发现自己同时使用这两种方法(ORM用于简单的CRUD和SQL/薄数据访问层用于报表)。
我认为对于读取操作应该使用普通的SQL语句,而对于增、删、改操作可以使用ORM。
性能一直是我非常关注的问题,特别是在Web应用程序中,但也包括代码可维护性和可读性。为了解决这些问题,我编写了SqlBuilder。
ORM不仅是可移植性(即使使用ORM,这也很难实现)。它为您提供的基本上是一个持久性存储的抽象层,在ORM工具中,它使您免于编写样板SQL查询(按主键或谓词选择、插入、更新和删除),并让您集中精力解决问题领域。
任何值得尊重的设计都需要对数据库进行一定程度的抽象,以处理阻抗失配。但最简单的第一步(对于大多数情况来说已经足够了)我期望是使用数据访问层(DAL),而不是笨重的ORM。你的选择不应该只在两个极端之间。
回答一条评论要求我描述如何区分DAL和ORM:
DAL是你自己编写的代码,可能从一个仅封装表格并将其字段映射为属性的类开始。ORM是代码,您不需要为其编写抽象机制,而是通过推断您的DBMS模式的其他属性(主键和外键)进行的。(这就是您发现自动抽象开始变得不完整的地方。我更喜欢有意识地告知它们,但这可能只是我的个人偏好)。
使我的ORM使用真正飞起来的关键是代码生成。我同意ORM路线在代码性能方面并不是最快的。但是当你有一个中等到大型的团队时,数据库正在快速变化,从数据库重新生成类和映射作为构建过程的一部分是令人惊叹的东西,特别是当你使用CI时。因此,你的代码可能不是最快的,但你的编码将是最快的——对于大多数项目,我知道我会选择哪个。
我的建议是,在架构仍然不确定的情况下使用ORM进行开发,使用性能分析来找到瓶颈,然后使用原始Sql来调整需要优化的区域。
另外一个想法是,如果以正确的方式使用Hibernate内置的缓存功能,可以经常实现巨大的性能提升。不再返回DB以读取参考数据。
没有一种通用的解决方案,这也适用于“我是否应该使用ORM”的问题。
我的建议是:如果您需要编写一个非常“数据”集中、没有太多其他逻辑的应用程序/工具,则我会使用纯SQL,因为SQL是这种应用程序的特定领域语言。
另一方面,如果我要编写一个包含大量“领域”逻辑的业务/企业应用程序,则我会编写一个丰富的类模型,可以在代码中表达这个领域。在这种情况下,ORM映射器可能非常有用,因为它会将很多冗长的代码交给您处理。