为什么我不需要功能语言如Scala的ORM?


30

我想知道是否可以在Spring + Hibernate项目中从Java切换到Scala,以利用一些Scala功能,例如模式匹配,Option以及对我来说似乎更简洁的语法。我一直在Scala生态系统中寻找默认的ORM,并且发现了类似Activate的想法(但大多数情况下,我尝试查找Hibernate是否可以与Scala一起使用)。搜索此内容,我已经在有关JPA + Scala 的Play文档中阅读了此内容。

但是最重​​要的一点是:如果您拥有功能语言的强大功能,您是否真的需要一个“关系到对象”映射器? 可能不会。JPA是一种抽象的Java数据转换能力不足的便捷方法,但是当您从Scala开始使用它时,确实感觉不对。

我对如何使用函数式编程来创建完整的应用程序没有深入的了解(这就是为什么我打算使用Scala以便使我能够逐步理解这一点,因为它结合了OO + Functional),所以我不知道为什么我不需要功能语言的ORM,以及解决领域模型持久性的功能方法是什么?

对于Scala,用于业务逻辑的DDD方法仍然有意义,不是吗?


3
这是一个基于意见的问题。Scala并不是纯粹的功能,它也是一种OO语言,因此可以解释为什么您仍然想要使用ORM工具。对于数据库映射,请参见例如:SlickSORMAnorm
Jesper 2015年

我不是在寻求意见,而是在问一些对功能范式有深刻理解的东西,这是实现持久性的方法。我知道Scala是混合的,我想将其OO部分用于DDD。所以你说,即使我使用Scala采取DDD方法,ORM也是要走的路吗?
gabrielgiussi 2015年

在函数式语言中,您主要处理的值不像对象那样具有标识。因此,您不需要变更跟踪,这是ORM的主要工作之一。

2
您可能会喜欢这个话题:从功能到响应-域建模模式
Jesper 2015年

5
你并不需要在ORM 任何一种主要语言。
GrandmasterB

Answers:


30

好吧,每当我们进行这样的讨论时,要做的一件重要的事情就是清楚地区分对象关系映射器(“ ORM”)和数据库抽象层。ORM是一种数据库抽象层,但并非所有数据库抽象层都是ORM。研究这一问题的一个好工具是Python流行的SQLAlchemy库,该库自称为“ SQL工具箱对象关系映射器”(我的黑体字),认为它们是不同的东西。正如他们在其主要功能页面中所述

无需ORM

SQLAlchemy由两个不同的组件组成,称为CoreORM。Core本身是功能齐全的SQL抽象工具包,可为各种DBAPI实现和行为提供平滑的抽象层,以及一种SQL Expression Language,该语言可通过生成的Python表达式表达SQL语言。一个既可以发出DDL语句又可以对现有模式进行内省的模式表示系统,以及一个允许将Python类型映射到数据库类型的类型系统,可以完善该系统。然后,对象关系映射器是基于Core构建的可选包。

首页描述了这样的ORM:

SQLAlchemy最著名的是对象关系映射器(ORM),它是提供数据映射器模式的可选组件,在该模式中,可以以开放式,多种方式将类映射到数据库-允许对象模型和数据库模式以从一开始就完全脱钩。

ORM的关键思想是尝试消除著名的对象关系阻抗不匹配。这意味着定义用户定义的类与数据库模式中的表之间的关系,并为应用程序的类提供自动的“保存”和“加载”操作。

相反,非ORM数据库抽象层倾向于更致力于关系数据模型和SQL,而不是完全面向对象。因此,与其在表和类之间不提供“映射”并向程序员隐藏数据库模式,不如它们向数据库公开给程序员,但具有更好的API和抽象。例如,SQL查询构建器允许您以编程方式生成复杂的SQL查询,而无需进行字符串操作(例如,来自Java的jOOQ库的示例):

// Typesafely execute the SQL statement directly with jOOQ
Result<Record3<String, String, String>> result =
    create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
          .from(BOOK)
          .join(AUTHOR)
          .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID))
          .where(BOOK.PUBLISHED_IN.equal(1948))
          .fetch();

现在,Play框架似乎与我刚刚描述的并不完全相同,但他们的论点似乎是在这个大致领域内:直接使用关系模型,而不是将其转换为类并从中转换回来。

jOOQ库是值得研究的一个对应的ORM。他们也有一些相关的博客条目,值得一读:


19

在您完成了大量功能编程之前,这很难解释。在面向对象的编程中,您的数据有点卡在一个对象中并停留在那里。该对象经过了一些传递,并进行了相当多的修改,但通常在该数据的生命周期中,基本上都使用相同的“标识”。

ORM通常围绕该范例进行设计。您从数据库中检索了一些数据,将其压缩为一个对象,可能会对其进行大量修改,完成后,您仍然拥有可以写回到数据库的相同对象。

函数式编程的工作方式有所不同。您的数据在其生命周期内不会保持单一身份。它被拆分,复制,共享和转换。它经过一系列函数,然后最终重组为所需的输出形式。为了使任何数据库API在功能性语言中显得自然,必须考虑到这一点,而JPA则没有考虑。


1
+1000坚持使用Scala就像是Java ++的人使我为语言的未来感到恐惧:(
Andres F.

9

在scala中,将数据库表映射到对象仍然很有用,并且有几种方法可以实现。

斯卡拉世界中一种流行的框架是光滑的。它不是ORM,因为它做的更少(即,在没有被告知明确进行联接的情况下,它不会获取关系)。

因此,您仍然将对象映射到数据库行,但是对象是不可变的(因此不会进行状态刷新),并且您使用monadic DSL显式执行查询。结果是您获得了ORM的许多“好”部分,而没有围绕可变性和不可预测的N + 1问题的问题。

应该注意的是,人们使用功能更薄的代码库(如anorm或直接的JDBC)也已经取得了巨大的成功,这些库变得更加薄弱。

doobie也是一个在JDBC上应用功能技术的出色库。

因此,对于数据库访问,您有很多选择,但是Hibernate(似乎是事实上的ORM)并不是最佳选择之一,因为它偏向于可变性。


0

即使使用面向对象的语言,也不需要ORM。

首先,谁说过您的数据应该从持久存储中物理复制到对象上?Smalltalk背后的一个人Alan Kay想要对象摆脱数据。他建议对象只能对存储其数据的某些区域进行引用。

第二-实现这一目标的最佳方法是什么?我建议您根据对象的职责来确定对象,而不要考虑它们所拥有的数据。如果您听说过CRC卡方法,则将其完全用于此目的。

最后,以防万一您回到OO领域,这是一种实现它的方法

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.