试图了解clojureql的开放全局和结果的目的。我首先阅读了这篇概述:How does ClojureQL compare to clojure.contrib.sql?
我认为由于某种原因,open-global将取代sql / with-connection,例如我认为这样可行:
(def db {...}) ; connection details omitted
(open-global db)
(println (:name (first @(table :users)))
然而,这不起作用。看来我需要做开放全局并将执行查询包装在(sql / with-connection数据库)中,这让我感到惊讶(我认为open-global提供了一个默认的全局可访问连接)。所以,由于情况似乎并非如此,我现在不知道它到底在做什么。
另外......结果与简单地用@执行查询有什么不同?因为似乎@(table:users)会给我一个序列,这个序列是执行查询的结果(不是那个with-results也是如此)?
答案 0 :(得分:3)
使用deref
(@
符号)与with-results之间的区别非常微妙。基本上两者都做同样的事情,唯一的区别是查询实际执行的那一刻。两者实际上只是apply-on
协议的Relation
方法的包装器,这里是with-results
的代码:
(defmacro with-results
[[results tble] & body]
`(apply-on ~tble (fn [~results] ~@body)))
对于deref
:
(deref [this]
(apply-on this doall))
正如您所看到的,deref
与以下内容完全相同:
(with-results [res (table :users)] (doall res))
如果查看doall
文档,您会发现它是一个用于遍历延迟序列以强制任何副作用的函数,结果是序列将被完全评估,因此不再懒惰,而是留在记忆中。
为了给你一个更实际的解释,使用deref
在调用它时实际执行查询,而使用with-results
时,查询将被懒惰地执行,即结果实际上是消耗的。
至于open-global
,你是对的,它确实应该打开一个全局可用的连接,当没有使用wiht-connection
指定一个时,ClojureQL将使用它。您正在观察的行为可能是一个错误,因此我建议您在IRC频道或Github上的ClojureQL问题跟踪器上报告。我有一段时间没有使用ClojureQL,但是看一下代码,它们似乎已经转换为使用clojure.java.jdbc
而不是clojure.contrib.sql
,可能会出现问题。