连接:发生了什么?

时间:2014-03-23 03:41:45

标签: jdbc clojure

在我的Clojure项目中,我将依赖项从[org.clojure/java.jdbc "0.2.3"]更改为[org.clojure/java.jdbc "0.3.3"]

我收到以下错误:

  

clojure.lang.Compiler $ CompilerException:java.lang.RuntimeException:没有这样的var:sql / with-connection,编译:(/ Volumes / HD2 / env / prj / restore / src / restore / db.clj:80 :5)

发生什么事了?这个功能是否已被弃用?

背景:我需要执行! 0.2.3没有它。 0.3.3有它,但它没有连接?!?

请帮忙。

3 个答案:

答案 0 :(得分:23)

with-connection不仅被认为对leonardoborges提到的原因有害,而且还使连接池更难处理。从特定连接中解耦函数数据库访问使得模型更容易。强制查询使用相同的连接应该是例外,而不是规则。因此,clojure.core / java.jdbc 0.3.0专门用于弃用with-connection。为了适应这种情况,需要更改整个API。

现在,每个数据库访问函数都将db规范作为参数。如果db-spec是连接池,则该函数将在其中一个连接上执行,否则将从db-spec创建隐式新连接。因此,当不使用连接池时,所有数据库访问函数都会导致连接。

这也意味着不能再懒惰地返回结果集。以前,处理延迟序列可能会在仍然在with-connection块内时推迟。现在需要在函数执行期间实现它们,或者可以关闭它的连接,或者可以从池中返回新连接以用于下一个访问函数。

因此,现在可以通过两个新的命名参数:row-fn:result-set-fn在函数本身的范围内完成处理。第一行转换每行,第二行转换行。如果:result-set-fn返回延迟序列,则稍后使用时会出现连接或结果集关闭异常。默认:result-set-fndoall。使用自己的时,请确保它已实现。

一般情况下,访问和连接是分离的。现在为例外:需要使用相同连接的函数。

其中最常见的是事务使用,它使用范围来指示事务的开始和结束。旧transaction仅提供此范围。新的with-db-transaction函数绑定了一个新的var和dp-spec。

此var将绑定到池中的一个特定连接,或者在未使用连接池时绑定到新创建的连接。块内使用的所有数据库访问函数都应使用var而不是db-spec参数。

(def db {..})

(with-db-transaction
  [c db]
  (let [from 1111
        to 2222
        sum 10
        saldo-from (query c ["select saldo from account where id=?" from]
                          :row-fn :saldo
                          :result-set-fn first)
        saldo-to (query c ["select saldo from account where id=?" to]
                        :row-fn :saldo
                        :result-set-fn first)]
    (update! c :account {:saldo (- saldo-from sum)} ["id=?" from])
    (update! c :account {:saldo (+ saldo-to sum)} ["id=?" to])))

将在开头发出begin transaction命令。所有访问都将使用现在专门传递给函数的相同连接,而不是通过动态范围魔术。如果没有生成异常,则会在范围的末尾给出commit

当一个特定的连接,但不需要事务机制时,with-db-connection函数具有相同的语义。因此,如果要执行命令来设置会话设置,并对该连接执行某些查询,则可以执行以下操作:

(def db {..})

(with-db-connection [c db]
                    (execute! c ["alter session set NLS_SORT='ITALIAN'"])
                    (query c ["select * from person where name=?" "Mario"]
                           :row-fn (comp concat (juxt :name :surname))))

连接池通常具有特定的on-openon-close命令,这些命令是其规范的一部分。使用该池中的所有连接将设置相同的会话设置,甚至根本不需要with-db-connection

答案 1 :(得分:5)

如@mac所述,with-connection已弃用。原因是它对客户端代码施加了不必要的约束,特别是在多线程环境中。

我建议您阅读斯图尔特·塞拉(Stuart Sierra)的this post阅读材料,并阅读此内容以及与动态范围相关的其他问题。

答案 2 :(得分:2)

clojure.java.jdbc.deprecated中找到3.3 with-connection。