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

欢迎!请参阅关于页面以获取更多关于如何使用这个网站的信息。

+4
尚未提供或无法显示图片 工具
编辑

大家好!

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

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

那么,我的选项有哪些呢?

编辑:目前数据库使用的是PostgreSQL

谢谢!

编辑2:感谢大家的回答,它们非常有帮助,我确实能够解决这个问题了!

6 答案

+4

已选择
 
最佳答案

你将使用哪种数据库?

如果你可以自己选择,正如Adrian提到的那样,请慎重考虑使用Datomic,因为它具有简单且高度灵活的数据模型。

如果你必须使用SQL,最直接的方式是next-jdbbc,它会返回查询结果为地图的列表。如果你不需要在数据上执行任何复杂的转换,最简单的方法是仅使用Clojure提供的强大函数来访问和操作数据。不必过分担心创建“领域对象”。Clojure Applied提供了一些关于如何结构化领域数据的实用建议。

如果需要进行复杂的转换,一个常见的技巧是“标准化”数据,即在更大的地图中使用“领域模型名称”作为一级键,每个记录的id作为二级键,然后将模型/表格行作为地图的列表。这允许您快速访问不同的数据块。这种技巧也常用于客户端,如果您需要编写单页应用程序(查看re-frame和fulcro)。

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

您还可以查看specter,这是一个执行数据转换的领域特定语言,尽管在我的想法中,它创建的复杂性与DataScript所要避免的复杂度相似。根据您的需求选择。

我想补充一点,我们经常使用clojure.spec来用代码描述数据库模式,这样我们就有以下几点:1)文档;2)验证代码;3)一种为测试生成随机符合数据的方式(这样我们就不必模拟数据库);4)一个“记录系统”,从中可以派生出列等的列表——我们使用宏从规格生成CRUD函数。
by
强烈推荐正常化。然而,我认为re-frame人群中这不是一个常见的做法。在re-frame的维基中简要提到了这一点,但似乎没有人真正使用它 https://github.com/Day8/re-frame/blob/master/docs/FAQs/DB_Normalisation.md
相比之下,归一化是om.next/fulcro的核心部分。
+4
by

我现在在手机上,所以不能详细解释
但请查看 https://docs.datomic.com/on-prem/schema.html

+1
by

首先,正如其他人提到的那样,学习一下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中,整个不匹配问题要小得多,因为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序列)或没有记录时为nil....我认为

在对数据进行转换等操作时,您具有所有那些基本但功能强大的Clojure函数,使得对map和seq的处理变得轻松简单。此外,在从PostgreSQL到Java,从Java到JS进行类型转换时,总会遇到一些小麻烦,但如果使用Luminus,您将直接获得那些帮助工具。例如,在我的闪卡应用中,我有很多时间戳(例如,您是什么时候回答卡片的正确答案的,您何时留下评论等),而日期类型一直很棘手(比如java.sql,java.util,joda等),但在开发这个应用时,我根本不必担心这些。Luminus会在幕后为您完成所有这些。此外,你还能够使用出色的clj(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

现在已经过去了一段时间,而且你提出的问题一直出现,我觉得可能可以问你一下,最终你决定使用什么方案了?还有,一切进展如何?你学到的最重要的教训是什么?如果重新来做,你会有什么不同之处吗?

...