为何选择 Prisma ORM?
在本页中,你将了解 Prisma ORM 的动机,以及它与传统 ORM 和 SQL 查询构建器等其他数据库工具的比较。
使用关系型数据库是应用程序开发中的一个主要瓶颈。调试 SQL 查询或复杂的 ORM 对象通常会耗费数小时的开发时间。
Prisma ORM 通过提供清晰且类型安全的 API 来提交数据库查询,并返回普通 JavaScript 对象,从而使开发人员能够轻松地理解他们的数据库查询。
TLDR
Prisma ORM 的主要目标是提高应用程序开发人员在使用数据库时的生产力。以下是 Prisma ORM 如何实现这一目标的几个例子:
- 以对象思维,而不是映射关系数据
- 查询而非类,以避免复杂的模型对象
- 数据库和应用程序模型的单一事实来源
- 健康的约束,防止常见的陷阱和反模式
- 一个让正确的事情变得简单的抽象(“成功之坑”)
- 类型安全的数据库查询,可在编译时验证
- 更少的样板代码,让开发人员专注于应用程序的重要部分
- 代码编辑器中的自动补全,无需查阅文档
本页的其余部分将讨论 Prisma ORM 如何与现有数据库工具进行比较。
SQL、传统 ORM 和其他数据库工具的问题
Node.js 和 TypeScript 生态系统中现有数据库工具的主要问题是,它们需要在生产力和控制之间做出重大权衡。
原生 SQL:完全控制,低生产力
使用原生 SQL(例如,使用原生 pg
或 mysql
Node.js 数据库驱动程序),你对数据库操作拥有完全控制权。然而,生产力会受到影响,因为向数据库发送纯 SQL 字符串很麻烦,并且会带来很多开销(手动连接处理、重复的样板代码等)。
这种方法的另一个主要问题是你无法获得查询结果的类型安全。当然,你可以手动输入结果,但这需要大量工作,并且每次更改数据库模式或查询以保持类型同步时,都需要进行重大重构。
此外,以纯字符串形式提交 SQL 查询意味着你无法在编辑器中获得任何自动补全功能。
SQL 查询构建器:高控制,中等生产力
一种既能保持高水平控制又能提高生产力的常见解决方案是使用 SQL 查询构建器(例如 knex.js)。这类工具提供了一种编程抽象来构造 SQL 查询。
SQL 查询构建器最大的缺点是,应用程序开发人员仍然需要用 SQL 的术语来思考他们的数据。这带来了将关系数据转换为对象的认知和实际成本。另一个问题是,如果你不完全清楚自己在 SQL 查询中正在做什么,就很容易自食其果。
传统 ORM:较少控制,更高生产力
传统 ORM 通过允许你将应用程序模型定义为类来抽象 SQL,这些类映射到数据库中的表。
“对象关系映射器”(ORM)旨在弥合程序员的朋友(对象)和数据库的原语(关系)之间的鸿沟。这些不同模型的原因既有文化上的,也有功能上的:程序员喜欢对象,因为它们封装了运行程序中单个事物的状态。数据库喜欢关系,因为它们更适合整个数据集的约束和整个数据集的有效访问模式。
然后,你可以通过调用模型类实例上的方法来读写数据。
这方便得多,也更接近开发人员思考数据时的心智模型。那么,有什么问题呢?
ORM 代表着一个泥潭,开始时一切顺利,但随着时间推移变得越来越复杂,不久便将用户困在一个没有明确界限、没有明确胜利条件、没有明确退出策略的承诺中。
作为一名应用程序开发人员,你对数据的心理模型是对象。而 SQL 中数据的心理模型则是表。
这两种不同数据表示形式之间的差异通常被称为对象关系阻抗不匹配。对象关系阻抗不匹配也是许多开发人员不喜欢使用传统 ORM 的主要原因。
例如,考虑每种方法如何组织数据和处理关系:
- 关系型数据库:数据通常是规范化的(扁平的),并使用外键在实体之间进行链接。然后需要对实体进行 JOIN 操作才能体现实际关系。
- 面向对象:对象可以是深层嵌套的结构,你可以简单地使用点表示法遍历关系。
这暗示了传统 ORM 的一个主要陷阱:虽然它们让你可以看似简单地使用熟悉的点表示法遍历关系,但实际上 ORM 在底层生成了 SQL JOIN,这些 JOIN 操作成本高昂,可能大幅降低应用程序的速度(其中一个症状是 n+1 问题)。
总而言之:传统 ORM 的吸引力在于它们承诺抽象关系模型,并纯粹从对象的角度思考数据。尽管这个前提很好,但它基于一个错误的假设,即关系数据可以轻易地映射到对象,这导致了许多复杂性和陷阱。
应用程序开发人员应该关注数据——而不是 SQL
尽管 SQL 在 1970 年代(!)就已开发出来,但它以令人印象深刻的方式经受住了时间的考验。然而,随着开发工具的进步和现代化,值得思考的是,SQL 是否真的是应用程序开发人员最佳的抽象工具?
毕竟,开发人员应该只关心实现某个功能所需的数据,而不是花费时间去弄清楚复杂的 SQL 查询,或为了满足需求而调整查询结果。
在应用程序开发中,还有另一个反对 SQL 的论点。如果你确切知道自己在做什么,SQL 的强大功能可能是一种福气,但其复杂性也可能是一种诅咒。即使是经验丰富的 SQL 用户,也难以预料到许多 反模式 和陷阱,这往往会以性能和数小时的调试时间为代价。
开发人员应该能够请求他们需要的数据,而不必担心在 SQL 查询中“做正确的事情”。他们应该使用一个能为他们做出正确决定的抽象。这可能意味着该抽象会施加某些“健康的”约束,以防止开发人员犯错。
Prisma ORM 提高开发人员的生产力
Prisma ORM 的主要目标是提高应用程序开发人员在使用数据库时的生产力。再次考虑生产力和控制之间的权衡,这就是 Prisma ORM 的定位: