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

欢迎!请查看关于页面了解更多关于如何使用本平台的信息。

+4
工具
编辑

大家好!

最近我决定将一个中型项目的副本(用Java、Spring Boot和Hibernate编写)创建成Clojure版本。我想知道在Clojure中以约定的方式进行数据、模型以及关系的建模应该怎么做?

我不认为它一定是对象或ORM,但我确实认为应该在代码中反映数据库或数据规范(这样开发者就可以知道从数据库查询什么,以及期待从那个查询中获得什么)。

那么,我的选择是什么呢?

编辑:目前数据库是PostgreSQL

谢谢!

编辑2:感谢所有 پاسخ‌ها،它们非常有帮助,我肯定能解决这个问题!

6 个答案

+4

选中
 
最佳答案

你将使用哪个数据库?

如果你可以选择一个,就像Adrian也提到的,严肃考虑使用Datomic,因为它具有简单且高度灵活的数据模型。

如果你必须使用SQL,最具直接性的方法是next-jdbc,它将查询结果返回为一系列的Map对象。如果你不需要对数据进行任何复杂的转换,最简单的方法是简单地使用Clojure广泛的功能来访问和操作数据。不要过分担心创建'域对象'。 Clojure Applied 提供了一些关于如何构建域数据的实用建议。

如果你需要进行复杂的数据转换,一种常见的技术是对数据进行'规范化',基本上创建一个包含'域模型名称'作为一级键和每个记录的ID作为二级键的大Map,然后是模型/表的行作为Map对象列表。这允许你快速访问数据的不同部分。这种技术也常用于客户端,如果需要编写单页应用(参见 re-framefulcro)。

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

你也可以看看 specter,一个用于执行数据转换的DSL,虽然在我看来,它创建的复杂性是DataScript避免的。无论什么对你最有用。

by
我还要补充一点,我们经常使用clojure.spec在代码中描述我们的数据库模式,以便我们能够有1) 文档 2) 验证代码 3) 一种生成随机符合测试规范的测试数据的方法(这样我们就不需要模拟数据库) 4) 一种"系统记录",从它可以推导出列等列表 - 我们使用宏从规范生成CRUD函数。
非常推荐范式化。然而,我认为在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。这将改变你对数据库的看法。

有一个SQL库受到Datomic pull api的极大影响 http://walkable.gitlab.io
它可以帮助你快速构建API。它提供了一个描述你表之间关系的表达方式,这样当更多的表被添加到系统中时,你就不需要为记住实现细节而焦虑。

顺便说一下,我认为编写Clojure代码的最新习惯是数据驱动。

0 投票

我认为这个问题没有唯一的正确答案……但我建议你考虑以下因素……你决定使用关系数据库(我认为这是完全可以的!)……那么有人可能会争辩说,首先你的问题是与ER-modeling等相关的,而不是真正与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查询...存储过程等...多棒啊!!....另外,比如说我想从Clojure切换到Java/Node等...由于使用hugsql你只是在操作SQL...以及非常少的元配置,这些配置以注释的形式存在...从这些注释中,你可以得到可以在运行查询时使用的Clojure函数...你可以以map的形式将这些参数传递给这些预处理语句...并得到一个记录的map输出,或者多个记录的map序列...以及null,表示没有记录...我想...

……在进行转换等操作时,您拥有所有基本的但强大的Clojure函数,使得对映射和序列的处理变得轻而易举。此外,在转换类型时总会有一些琐碎的事情,比如从Postgres到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?(不确定是否真的叫这个名字)……等等!)。

……无论如何,我采用了基于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

这再次紧密地服务于我的用例,但也许它能启发你意识到在Clojure中,你可以相当容易且强大地做自己想做的事情,而不必过分依赖库和依赖项。

0 投票

现在有些时间过去了,由于你问的问题一直出现,我想也许我可以问你,你最终决定使用什么。事情的结果如何?你学到了哪些最重要的教训?如果你重做的话,你想要做哪些不同的事情?

...