我经常需要从数据库服务器加载大量数据。有时它有数百万行甚至更多。所以我试着懒洋洋地下载数据。那就是我想做的事情:我想得到一个懒惰的序列并从服务器拉取数据部分,即如果行数大于500,我想主要得到那个懒惰序列前500个元素的帮助,然后通过另一个请求我想要接收下一个500个元素,依此类推,直到我收到服务器上的所有数据。
但我有一个问题。 Clojure jdbc实现了整个延迟序列,但我想部分地从中获取数据。 我研究这个问题并找到关于类似问题的好回复: clojure.java.jdbc lazy query
我拿了这个例子写了这个:
(defn get_data
[arg1 arg2]
(let [full-db-spec (get ...)
sql_query (get ...)
row-n (atom 0)
prepared-statement (-> full-db-spec
(jdbc/get-connection)
(jdbc/prepare-statement sql_query {:fetch-size 3}))]
(jdbc/with-db-transaction [tx full-db-spec]
(jdbc/query full-db-spec [prepared-statement arg1 arg2]
{:fetch-size 3
:row-fn (fn [r] (do (prn "r" @row-n) (swap! row-n inc) r))
:result-set-fn identity}))))
这里我想得到一个懒惰序列,以便从这个懒惰序列中进一步部分提取数据。但是当:result-set-fn
包含identity
或(take 500 ...)
时,代码会返回错误:The result set is closed.
为什么?但是当我改变:result-set-fn为first或doall或last时它工作正常,但它实现了完整的懒惰序列!
我用:
[com.microsoft.sqlserver/mssql-jdbc "6.3.3.jre8-preview"]
(我在postgresql [org.postgresql/postgresql "9.4.1212.jre7"]
上测试。结果相同)答案 0 :(得分:4)
该延迟序列正在从您的连接读取值,但该连接在with-db-transaction
范围之外关闭。您需要在该范围内实现/进行进一步处理。