Clojure中的连接池

时间:2019-02-10 06:30:34

标签: clojure

我无法理解pool-dbconnection函数的使用 在此connection pooling guide中。

(defn- get-pool
    "Creates Database connection pool to be used in queries"
    [{:keys [host-port db-name username password]}]
    (let [pool (doto (ComboPooledDataSource.)
                   (.setDriverClass "com.mysql.cj.jdbc.Driver")
                   (.setJdbcUrl (str "jdbc:mysql://"
                                     host-port
                                     "/" db-name))
                   (.setUser username)
                   (.setPassword password)
                   ;; expire excess connections after 30 minutes of inactivity:
                   (.setMaxIdleTimeExcessConnections (* 30 60))
                   ;; expire connections after 3 hours of inactivity:
                   (.setMaxIdleTime (* 3 60 60)))]
        {:datasource pool}))


(def pool-db (delay (get-pool db-spec)))


(defn connection [] @pool-db)

; usage in code
(jdbc/query (connection) ["Select SUM(1, 2, 3)"])

我们为什么不能简单地做?

(def connection (get-pool db-spec))

; usage in code
(jdbc/query connection ["SELECT SUM(1, 2, 3)"])

4 个答案:

答案 0 :(得分:4)

延迟确保您在首次尝试使用连接池时创建连接池,而不是在加载名称空间时创建连接池。

这是一个好主意,因为您的连接池可能由于多种原因而无法创建,并且如果在命名空间加载期间失败,您将得到一些奇怪的行为-创建失败的连接池后的任何定义都不会例如被评估。

通常,应构造顶级var定义,以使它们在运行时不会失败。

请记住,它们也可能在AOT编译过程中进行评估,如下文合金所示。

答案 1 :(得分:0)

在您的应用程序中,您只想创建一个池并重用它。因此,delay用于包装(get-pool db-spec)方法,以便仅在第一次使用deref / @强制使用该方法时才调用该方法,并将其缓存在随后的池中返回强制通话

答案 2 :(得分:0)

区别在于,在延迟版本中,仅当调用池时才会创建池(如果所有内容都已缓存,则可能不会创建),但是非延迟版本无论如何都将实例化池,即始终,即使不使用数据库连接。

delay仅在调用deref时运行,否则不执行任何操作。

答案 3 :(得分:0)

我建议您使用现有的库来处理连接池,例如hikari-cp,它是高度可配置的,并且可以在许多SQL实现中使用。