首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ORM for clojure?

ORM for clojure?
EN

Stack Overflow用户
提问于 2011-09-09 01:09:39
回答 8查看 10.9K关注 0票数 39

我读到了这个关于clojure web堆栈的站点:

http://brehaut.net/blog/2011/ring_introduction

关于clojure的ORM,它是这样说的:

“由于显而易见的原因,没有用于Clojure的SQL/关系型DB ORM。”

我能看到的明显原因是,当您执行clojure.contrib.sql或clojureql查询时,会自动映射到object。然而,似乎需要一些额外的工作来做一对多或多对多的关系(尽管可能不是太多的工作)。

我发现这篇文章是针对一对多的:http://briancarper.net/blog/493/

我不确定我是否同意这一点;它似乎假设从数据库中拉出两个表,然后在内存中过滤连接的表。在实践中,我认为sql查询将指定where标准。

所以我想知道,是否有一些相当明显的方法可以通过clojureql或clojure.contrib.sql自动执行一对多关系?我能想到的唯一一件事是这样的(使用典型的博客文章/评论示例):

代码语言:javascript
复制
(defn post [id] 
    @(-> (table :posts)
        (select (where :id id))))
(defn comments [post_id]
    @(-> (table :comments) 
         (select (where :post_id post_id))))
(defn post-and-comments [id]
    (assoc (post id) :comments (comments id)))

有没有办法将这个概念自动化,或者这是最好的方法吗?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2011-09-16 15:35:09

据我所知,仍然没有高级库来创建复杂的关系查询。有很多方法可以解决这个问题(您提供的链接是单向的),但是即使ClojureQL提供了一个非常好的可以构建的数字用户线,它仍然缺少一些重要的功能。下面是一个生成重叠连接的宏的快速而肮脏的示例:

代码语言:javascript
复制
(defn parent-id [parent]
  (let [id (str (apply str (butlast (name parent))) "_id")]
    (keyword (str (name parent) "." id))))

(defn child-id [parent child]
  (let [parent (apply str (butlast (name parent)))]
    (keyword (str (name child) "."  parent "_id"))))

(defn join-on [query parent child]
  `(join ~(or query `(table ~parent)) (table ~child)
         (where
          (~'= ~(parent-id parent)
               ~(child-id parent child)))))

(defn zip [a b] (map #(vector %1 %2) a b))

(defmacro include [parent & tables]
  (let [pairs (zip (conj tables parent) tables)]
    (reduce (fn [query [parent child]] (join-on query parent child)) nil pairs)))

这样,您就可以执行(include :users :posts :comments)并从中获得以下SQL:

代码语言:javascript
复制
SELECT users.*,posts.*,comments.*
  FROM users
  JOIN posts ON (users.user_id = posts.user_id)
  JOIN comments ON (posts.post_id = comments.post_id)

不过,这项技术有一个主要问题。主要问题是,所有表的返回列都将捆绑到同一映射中。由于不能自动限定列名,因此如果不同表中存在名称相似的列,则不会起作用。这还将防止您在没有访问架构的情况下对结果进行分组。我认为没有办法避免不知道数据库模式来处理这类事情,所以仍然有很多工作要做。我认为ClojureQL将始终是一个低级库,所以您需要等待其他高级库出现或创建您自己的库。

要创建这样的库,您可以随时查看JDBC的DatabaseMetaData类,以提供有关数据库模式的信息。我仍然在开发一个使用它的Lobos数据库分析器(以及一些定制的东西),但是我还远没有开始处理SQL查询,我可能会在2.0版中添加它。

票数 11
EN

Stack Overflow用户

发布于 2012-01-23 02:31:25

我很久以前就问过这个问题,但我遇到了以下问题,并决定将其添加为答案,以防有人感兴趣:

http://sqlkorma.com/

票数 30
EN

Stack Overflow用户

发布于 2011-09-18 07:08:49

在Clojure中不需要ORM的“显而易见的”原因是,惯用的Clojure本身没有对象。

在Clojure程序中表示数据的最佳方式是作为简单数据结构(映射和向量)的惰性序列。与成熟的ORM相比,将这些映射到SQL行要简单得多,并且阻抗不匹配的情况也要少得多。

另外,关于你的问题中关于形成一个复杂的SQL查询的部分...仔细阅读您的代码,它并不比SQL本身有任何明显的优势。不要害怕SQL!它的功能非常强大:关系数据操作。

票数 29
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7351891

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档