1

最初我想问为什么我在结果集上调用 (seq) 作为空性测试时遇到问题,但一些研究表明这显然是因为 jdbc 光标没有移动到任何地方。很好,花花公子。如果我不知道它的名字,有没有办法在结果集上调用 next() ?我可以将它绑定到 clojure 中的符号,但我无法弄清楚如何从那里调用该方法。

编辑:如果不清楚,我指的是 java resultSet 方法 next(),而不是 clojure (next)

编辑#2 这是一个代码片段:

(defn user-exists? [email]
  (with-connection db
   (with-query-results res ["SELECT guid from users WHERE email=?" email]
    (.next res)
    (seq res))))

(感谢.next 的帮助,顺便说一句......还没有做太多的 java 互操作)

尽管如此,如果查询没有返回任何内容,使用 (seq) 会引发 NullPointerException。我想知道是否有更清洁,惯用的方式来做到这一点?

4

2 回答 2

3

res 将绑定到基于 ResultSet 的 Clojure 序列,其中每个项目是结果记录的映射,其中输出列名称作为键中的关键字。您无法访问底层的实际 ResultSet 对象。

通常,您根本不会调用 next。要成为惯用的 Clojure,您将利用对序列(map、filter、reduce 等)进行操作的庞大函数库来生成输出。在这里你可能会说:

(with-query-results res ["SELECT guid from users WHERE email=?" email]
  (map :guid res))

这会将 :guid 作为函数应用于 res seqeuence 并检索每条记录中 guid 的列值,为您返回所有 guid 的新序列。然后,您可以将该地图包装在过滤器或您需要的任何其他东西中。

在这种情况下,seq应该是您想要的,但我认为抽象有点泄漏。当我尝试它时,我得到了java.sql.SQLRecoverableException: Closed Resultset: next这对我来说意味着 ResultSet 在抽象中被关闭得太早了。但是,我发现empty?这个用例工作正常。

(defn user-exists? [email]
  (with-connection db
   (with-query-results res ["SELECT guid from users WHERE email=?" email]
    (.next res)
    (not (empty? res)))))

对我来说,这似乎是 clojure.core/resultset-seq 中的一个错误,我在这里将其报告为CLJ-676

于 2010-11-16T21:43:55.877 回答
1

怎么样

(defn user-exists? [email]
  (with-connection db
    (with-query-results res ["SELECT guid from users WHERE email=?" email]
      (first res))))

如果返回一行,或者没有匹配的行,那应该返回一些东西。nil

您之前的查询失败了,因为res是对 的调用的值(resultset-seq x),因此您不能ResultSet.next()在其上使用 Java,也不想seq再次调用它。

如前所述,您必须评估(and ) 打开的resultset-seq时间,因此您必须有ResultSetConnection

(defn users-with-email [email]
  (with-connection db
    (with-query-results res ["SELECT guid from users WHERE email=?" email]
      (doall res))))
于 2010-11-19T21:46:20.410 回答