我读到了这个关于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自动执行一对多关系?我能想到的唯一一件事是这样的(使用典型的博客文章/评论示例):
(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)))有没有办法将这个概念自动化,或者这是最好的方法吗?
发布于 2011-09-16 15:35:09
据我所知,仍然没有高级库来创建复杂的关系查询。有很多方法可以解决这个问题(您提供的链接是单向的),但是即使ClojureQL提供了一个非常好的可以构建的数字用户线,它仍然缺少一些重要的功能。下面是一个生成重叠连接的宏的快速而肮脏的示例:
(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:
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版中添加它。
发布于 2012-01-23 02:31:25
我很久以前就问过这个问题,但我遇到了以下问题,并决定将其添加为答案,以防有人感兴趣:
http://sqlkorma.com/
发布于 2011-09-18 07:08:49
在Clojure中不需要ORM的“显而易见的”原因是,惯用的Clojure本身没有对象。
在Clojure程序中表示数据的最佳方式是作为简单数据结构(映射和向量)的惰性序列。与成熟的ORM相比,将这些映射到SQL行要简单得多,并且阻抗不匹配的情况也要少得多。
另外,关于你的问题中关于形成一个复杂的SQL查询的部分...仔细阅读您的代码,它并不比SQL本身有任何明显的优势。不要害怕SQL!它的功能非常强大:关系数据操作。
https://stackoverflow.com/questions/7351891
复制相似问题