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