请在2024年Clojure状态调查!中分享您的想法。

欢迎!有关如何运作的信息,请参阅关于页面。

+4投票
工具
编辑

大家好!

最近我决定复制一个中型的项目(该项目是用Java的Spring Boot和Hibernate编写的)到Clojure中。我不知道如何以Clojure的方式建模数据和模型以及它们之间的关系?

我认为这不一定必须是对象或ORM,但我认为在代码中应该有一些类型的数据库或数据规格的表示(这样开发者就可以知道从数据库查询什么,以及可以期待从查询中得到什么)。

那么,我的选择有哪些?

修订版:目前数据库是PostgreSQL

谢谢!

修订版2:感谢大家的回答,它们非常有帮助,我现在肯定能解决这个问题了!

6个答案

+4投票

被选中
 
最佳答案

你将使用哪个数据库?

如果可以自己选择,正如Adrian所说,请认真考虑使用Datomic。因为Datomic具有简单且高度灵活的数据模型。

如果必须使用SQL,最直接的方法是使用next-jdbbc,它将查询结果作为映射列表返回。如果你不需要对数据进行任何复杂的转换, simplest 方法是简单地使用Clojure丰富的函数来访问和操作数据。不需要过分担心创建“领域对象”。《Clojure Applied》在如何结构域数据方面提供了一些实用建议。

如果您需要进行复杂的转换,一个常用的技术是对数据进行“规范化”,基本创建一个使用“领域模型名称”作为顶级密钥、每个记录的id作为二级密钥的大映射,以及将模型/表行作为映射列表。这允许您快速访问不同的数据片段。这种方法在客户端也经常使用,如果您需要编写单页应用程序(参考re-framefulcro)。

DataScript 是一个类似于Datomic的数据库,但是在内存中的。它轻量到足以在服务器和客户端使用。您定义一个模式,添加您的数据,然后可以对它执行datalog查询和抽取,利用它简单灵活的数据模型。因此,即使使用SQL数据库,也可以查询一些数据,将结果加载到DataScript中,然后在内存中进行操作和查询,最后写入结果。

您还可以考虑 specter,一个用于执行数据转换的领域特定语言,尽管我认为它创建了类似于DataScript所避免的复杂性。无论哪种方法适合您。

我还要补充的是,我们通常使用clojure.spec来用代码描述数据库模式,以便我们有1)文档 2)验证代码 3)为测试生成随机符合规范的数据的方式(因此我们不需要模拟数据库) 4)从其中推导出列、等信息的“记录系统” -- 我们使用宏从规范生成CRUD函数。
强烈建议进行规范化。然而,我认为在 re-frame 社区中这不是一个常用的做法。它在 re-frame 的维基百科中简要提及,但似乎没有人真正使用它 https://github.com/Day8/re-frame/blob/master/docs/FAQs/DB_Normalisation.md
相比之下,规范化是 om.next/fulcro 的核心部分。
+4投票

我现在在用手机,所以解释不多
但可以查看https://docs.datomic.com/on-prem/schema.html

+1

首先,正如其他人提到的,学习一下 Datomic 或 Datascript。这将改变你对数据库的看法。

有一个受 Datomic pull api 影响很大的 SQL 库 http://walkable.gitlab.io
它可以帮助你快速构建 API。它提供了一种描述您表之间关系的方式,这样你的思维就不会因为记住实现细节而在添加更多表到系统时崩溃。

Btw,在我看来,编写 Clojure 代码的最新习惯是用数据驱动。

0

我认为这个问题的答案并非唯一……但我建议你考虑以下……你选择使用关系数据库(我认为这很合适!)……所以有人可能会争辩说……首先,你的问题是与ER建模等相关,而不是与Clojure本身相关。:-)

……我的意思是什么……嗯……你已经提到了ORM。当你使用Java时,关系世界和面向对象世界之间的“阻抗/范例不匹配”通常会导致大量的杂乱/头痛……等等。

好吧……但当你使用ORM时,你会付出巨大的代价(我认为如此),也就是说,如果你不谨慎于你所做的事情,比如Hibernate,可能会生成一些极度荒谬的查询……比如在笨拙地获取某种树形结构时,生成的SQL可能相当愚蠢。显然,Hibernate真的很强大……你可以集成非常复杂的缓存等等。但是,我认为要做好Hibernate并不是那么容易/简单。

所以,即使是使用Java,我也建议首先考虑使用Spring JDBC数据访问,因为……正如我所说的,JPA确实增加了许多复杂性。(……因此,问问你自己你是否真的需要JPA。)

……无论如何,我想说的是,关系数据库很棒,SQL很棒,PostgreSQL很棒!!!许多编程语言的缺点就是,与关系技术交互往往真的很痛苦,所以你开始建立各种工具(如ORM等)来让你的人生更加顺利。(……我们在谈论疗法,而不是疗法。)

……现在我想争辩的是,由于Clojure不是围绕Person等类构建的,而是有一些强大的集合,所以Clojure的整个不匹配问题要小得多,所以你就可以继续前行了。:-)

……所以让我们更具体一点,我已经使用Clojure(script)构建了这个闪卡SAP。

……现在,我对很多事都不是太满意。例如,我真的想从Bootstrap过渡到Bulma等等。这是我做的第一个非平凡的Clojure项目,所以显然我犯了很多错误。我将会尽快进行重构/改进。但主要观点是我最不担心的是PostgreSQL/关系型数据库这部分。

……我使用了Luminus模板来设置PostgreSQL项目。这个设置包括hugsql(一个拥抱SQL的Clojure库)。然后你可以在完全不依赖于任何应用程序编程语言的情况下进行DDL/模式等设置,你的PostgreSQL查询,存储过程等等等。这样太棒了!此外,假设我想从Clojure切换到Java/Node等任意语言,我的整个数据库/持久层东西可以基本上保持原样,因为有了hugsql,你实际上只是在做SQL。还有非常少的元配置东西你放在评论里。通过这些评论,你将得到可以用来运行查询的Clojure函数。你可以用map的形式将这些参数传递给这些预处理语句,并得到对于一个或n个记录的map形式的输出,以及对于没有记录的nil。我想是这样的。

... 对于进行变换等操作,您拥有所有的基本但强大的Clojure函数,使按摩映射和序列变得轻而易举......还总会有一点点类型转换的东西......从PostgreSQL到Java,从Java到JS时......但如果您使用Luminus,您将会直接获得这些辅助工具......所以比如在我的闪卡应用中,我有许多时间戳......(...你是什么时候得到某张卡片正确答案的,你什么时候离开了评论等等等等......)......并且日期类型一直都很棘手......java.sql、java.util、joda等等......但当我开发这个应用时,我真的不需要担心任何这些事情......Luminus会为您在幕后处理好这些事务......另外......使用优秀的Clojure/Script时间库......( https://github.com/dm3/clojure.java-time / https://github.com/andrewmcveigh/cljs-time )......您可以编写您的与时间相关的代码......它将在中间件以及前端上都能工作......( ...有些小的例外......)......(... Luminus还提供了需要的transit-adapter?...不是很确定它是不是这个名字...) 等等的东西!!...

...无论如何......我遵循了简单原则的基于策略,我对此非常满意......你们可以随意评估......:-)

0

我最近将一个运行了13年的Java/Hibernate/MySQL设计迁移到了Clojure/Datomic

我编写了一个库,用于读取MySQL表模式,创建一个抽象的表规范,然后使用该规范创建Datomic模式并将所有数据迁移到Datomic。您可以查看它以获得灵感(我尝试将其编写得尽可能一般化,但它相当紧密地集中在我的用例上)
https://github.com/thosmos/mysql-to-datomic

然而,主要的是我创建了自己的抽象数据规范来描述表格、列和外部键,这样我不仅能够在Datomic中生成模式,而且后来还可以通过这个抽象规范自动生成GraphQL和EQL API以及带有链接子表和数据验证的前端CRUD数据输入表单。我已经尝试将这个模型定义规范的精华抽离到一个最小库中
https://github.com/thosmos/domain-spec

这又紧密地服务于我的用例,但它可能激发您去意识到,在Clojure中,您可以非常容易且强大地独立于库和依赖项完成自己的事情。

0

现在已经过去了一段时间,由于你提出的问题总是一再出现,我觉得可以问你一下,最终你决定选哪个方案?事情最后是如何发展的?你认为最重要的经验教训是什么?如果你要重做,有什么不同的事情你想做?

...