Kev*_*vin 38 clojure clojureql
我正在阅读这个关于clojure web堆栈的网站:
http://brehaut.net/blog/2011/ring_introduction
对于clojure,它有关于ORM的说法:
"出于显而易见的原因,Clojure没有SQL/Relational DB ORM."
我可以看到的显而易见的原因是,当您执行clojure.contrib.sql或clojureql查询时,将自动映射到对象.然而,似乎需要一些额外的工作来做一对多或多对多的关系(尽管可能没有太多的工作).
我发现这写了一对多: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)))
Run Code Online (Sandbox Code Playgroud)
有没有什么方法可以自动化这个概念,还是这样做得好?
lev*_*and 29
在Clojure中你不需要ORM的"明显"原因是因为惯用的Clojure本身没有对象.
在Clojure程序中表示数据的最佳方法是简单数据结构(映射和向量)的延迟seqs.与完全成熟的ORM相比,将这些映射到SQL行要简单得多,并且阻抗不匹配的程度要小得多.
另外,关于形成复杂SQL查询的问题部分......阅读代码,它实际上并没有比SQL本身更明显的优势.不要害怕SQL!它的作用非常棒:关系数据操作.
Nic*_*roi 10
仍然没有高级库来创建我所知道的复杂关系查询.有很多方法可以解决这个问题(你提供的链接是一种方式),但即使ClojureQL提供了一个非常好的DSL,你可以依赖它,它仍然会遗漏一些重要的功能.这是一个生成叠加连接的宏的快速而肮脏的示例:
(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)))
Run Code Online (Sandbox Code Playgroud)
有了这个,你可以做到(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)
Run Code Online (Sandbox Code Playgroud)
但是这种技术存在一个主要问题.主要问题是所有表的返回列将捆绑在同一个映射中.由于列名称不能自动限定,如果在不同的表中有类似名称的列,则它将不起作用.这也会阻止您在无法访问架构的情况下对结果进行分组.我认为没有办法知道这类事情的数据库架构,所以还有很多工作要做.我认为ClojureQL将始终保持低级库,因此您需要等待其他更高级别的库存在或创建自己的库.
要创建这样的库,您可以随时查看JDBC的DatabaseMetaData类,以提供有关数据库模式的信息.我还在为使用它的Lobos(以及一些自定义的东西)开发数据库分析器,但我还远未开始研究SQL查询,我可能会在2.0版本中添加它.
冒着与一些SO重击手一起在水中游泳的风险(彻底混合我的比喻;) - 对于绝大多数情况来说,ORM的最佳特征之一肯定是,务实的程序员必须永远不要使用甚至考虑SQL.在最坏的情况下,可能需要一些带有几个查询结果的hacky编程,因为当需要进行优化时,这将被转换为原始SQL,当然,;).
要说"明显"原因不需要ORM,有点遗漏了这一点.进一步开始使用DSL来建模SQL正在加剧这个错误.在绝大多数Web框架中,对象模型是用于描述由Web应用程序存储的数据的DSL,而SQL仅仅是将其传递给数据库所需的声明性语言.
使用ROR,django或Spring时的步骤顺序:
好的,所以你可能会使用稍微不同的顺序,但希望你明白这一点.思考SQL或描述它的DSL是一个很长的路要走.相反,模型层将所有SQL抽象化,允许我们创建数据对象,这些数据对象模拟我们希望在网站中使用的数据.
我完全同意OOP不是银弹,但是,在Web框架中建模数据肯定是有益的,并且利用clojure定义和操作Java类的能力似乎是一个很好的匹配.
问题中的例子清楚地表明了SQL的痛苦程度,而像Korma这样的DSL只是一个部分解决方案:"我们假设我们在数据库中有一些表......" - 呃,我以为我的DSL会创建那些为了我?或者这只是OOP语言做得更好的东西?;)
| 归档时间: |
|
| 查看次数: |
9723 次 |
| 最近记录: |