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

欢迎!请查阅关于页面以了解更多关于如何使用本表的说明。

+4
工具
修改

大家好!

最近,我决定将一个中等规模的项目(用Java和Spring Boot及Hibernate编写)复制到一个Clojure项目中。我想知道如何以Clojure的本义方式建模数据、模型和相关关系?

我认为这不一定应该是 对象 或ORM,但我确实认为应该有一些数据库或数据规范(data spec)的方案反映在代码中(这样,开发者就可以知道从数据库中查询什么以及期望从查询中获取什么)。

所以,我有什么选择?

编辑:到目前为止,数据库是PostgreSQL

谢谢!

编辑2:感谢你们的答案,它们非常有用,我肯定能够解决这个问题了!

6 个答案

+4

被选中
 
最佳答案

您将使用哪个数据库?

如果您可以自行选择,正如Adrian所提到的,请认真考虑Datomic。因为它具有简单且高度灵活的数据模型。

如果您必须使用SQL,最直接的方法是使用next-jdbbc,它会以列表的形式返回查询结果。如果您不必对数据进行任何复杂的转换,最简单的方法是直接使用Clojure丰富的函数来访问和操作数据。不必过于担心创建‘域对象’。《Clojure实战》提供了一些有关如何结构化域数据的实用建议。Clojure实战

如果您需要进行复杂的转换,一个常用技术是将数据‘标准化’,即在包含‘域模型名称’的一级键和每个记录的ID作为二级键的大映射中创建。然后,将模型/表行作为映射的列表。这使您可以快速访问不同的数据部分。此技术通常也用于客户端,如果您需要编写单页应用程序(查看re-framefulcro)。

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

您还可以查看specter,这是一种执行数据转换的domain-specific language,尽管在我看来,它创建了一种类似于DataScript避免的复杂性。无论什么对您有效。

by
我只想补充说,我们通常使用clojure.spec在代码中描述数据库架构,这样我们就有了1)文档2)验证代码3)一种生成随机、符合测试规范的数据的方法(这样我们就无需模拟数据库)4)一个从其中推导列列表等的“记录系统”--我们使用宏从Specs生成CRUD函数。
by
强烈推荐标准化。然而,我认为它在re-frame人员中不是一种常见的做法。它在re-frame的wiki中简短提到,但似乎没有人真正使用它 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,我认为最新 idiomatic 的 Clojure 编程方式是数据驱动。

0

我认为这个问题没有唯一的正确答案……但我建议你考虑以下……你决定使用关系型数据库(我认为这完全可以接受!)……因此,有人可能会说……首先,你的问题与 ER 模型等密切相关……而不仅仅是关于 Clojure…… :-)

……我的意思是什么……嗯……你提到了 ORM……当你在使用 Java 时,关系型和面向对象世界之间的“阻抗/范式不匹配”,很多时候会导致大量混乱/痛苦……等等。

好吧……但是当你使用 ORM 时,你确实会支付高昂的复杂度代价(我认为)……也就是说,如果你不仔细考虑你做的事情,例如 hibernate,它可能会产生最疯狂的事情/查询……例如,当天真地获取某种树结构时,生成的 SQL 可能相当愚蠢……当然,hibernate 非常强大……你可以集成非常复杂的缓存等等……尽管如此……要做得好/正确地使用 hibernate……我认为并不那么容易/直接……

所以...即便是使用Java,我也建议首先考虑Spring JDBC数据访问...因为...正如我所说的...JPA确实增加了不少复杂性...(因此,请自问一下,你是否真的需要JPA...)

...但无论如何,我想说的是,关系型数据库很棒...SQL很棒...PostgreSQL也棒!!!很多编程语言的麻烦就在于与关系型技术交互往往非常痛苦...所以我们开始构建各种工具,例如ORM等,以某种方式使生活更加容易...(...所以我们谈论的是疗法,而不是治愈...)

...现在,我想论证的是,使用Clojure,整个不匹配问题要轻微得多,因为Clojure不是围绕Person等类构建的,而是你有几个强大的集合,这样就足够了 :-)....

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

...现在,有很多我不太满意的地方...例如,我真的很想从Bootstrap切换到Bulma等等......这是我做的第一个非平凡规模的Clojure项目...所以显然我犯了很多错误...我会尽快尝试重构/改进这些东西...但主要难点是,我对PostgreSQL/关系型数据库部分最不担心...

....我用luminus模板设置了PostgreSQL项目...这个设置包括hugsql (一个拥抱SQL的Clojure库)....然后你可以进行DDL/模式设置...你的PostgreSQL查询...存储过程等等...以一种完全独立于任何应用程序编程语言的方式...只需使用你的PostgreSQL工具/专业知识...多么棒啊!!!!.....另外,比如说我想从Clojure切换到Java/Node等...好吧,我的整个数据库/持久层东西几乎可以保持不变...因为使用hugsql,你实际上只是在完成SQL...另外还有很少的元配置事物,你可以在注释中放入...从这些注释中,你可以得到可以运行查询的Clojure函数...你可以将作为map形式的参数传递给这些预编译语句...并获得作为单个记录的map或n个记录的map序列...以及nil表示没有记录...我想是这样...

....对于进行转换等操作,你拥有所有基本但强大的Clojure函数,这使得操纵map和seq变得简单...另外,从PostgreSQL到Java,从Java到JS的转换一直有一点类型转换的事情...但是如果你使用luminus...你将获得这些内置的帮助器...所以比如在我的闪卡应用中,我有很多时间戳...(...当你回答某张卡片的正确答案是什么时候...你是什么时候留下评论的等等...)...日期类型始终很棘手...java.sql、java.util、joda等...但在做这个应用时,我真的不需要担心这些事情...luminus会为您在幕后完成这一切...另外,使用优秀的cloj(script)时间库...( https://github.com/dm3/clojure.java-time / https://github.com/andrewmcveigh/cljs-time )....你可以编写你的时间相关代码...并且它将在中间件以及前端上生效(...会有一些轻微的例外...)(...luminus还提供了必要的transit-adapter? ( 不确定这个名字实际是否如此...) stuff also!!! )....

...无论如何...我选择了基于KISS原则的策略...对此我相当满意...请随意看待它...:-)

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

这 again 紧密服务于我的用例,但或许它能激发你意识到,在Clojure中,你可以轻松且强大地做自己想做的事情,不必过分依赖库和依赖。

0

现在有一段时间过去了,考虑到你问的问题一直存在,我想或许我可以问你,你最后决定使用什么。还有,事情进展得怎么样?你学到了最重要的经验是什么?如果你再次这么做,你会有什么不同的做法?

...