【发布时间】:2011-06-14 13:18:41
【问题描述】:
我有一个通过clojure-sql获取JDBC元数据的函数
(ns relink
(:require
[clojure.contrib.sql :as sql]
[clojure.string :as str]
))
(let [db-host "localhost"
db-port 1433
db-name "databasename"]
(def db {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver"
:subprotocol "sqlserver"
:subname (str "//" db-host ":" db-port)
:databasename db-name
:user "user"
:password "password"}))
(defn get-table-metadata
"Take database spec, return all table names from the database metadata"
[db]
(sql/with-connection db
(doall
(resultset-seq
(.getTables
(.getMetaData (sql/connection))
nil nil "%" (into-array '("TABLE")))))))
(get-table-metadata db)
现在我想扩展该函数以使用其他 SQL 元数据,方法是将 java 方法调用包装在 clojure 函数中作为参数,如下所示:
(get-sql-metadata db .getTables nil nil "%" (into-array '("TABLE")))
如果不将 (.getMetaData (sql/connection)) 也放入函数参数中,似乎无法完成此操作。
(get-sql-metadata db #(.getTables (.getMetaData (sql/connection)) nil nil "%" (into-array '("TABLE"))))
但是,我想在 get-sql-metadata 函数中将其抽象出来,因为它对于所有元数据方法调用都是相同的。
我尝试用 doto、..、-> 和 (. 符号重写 resultset-seq 中的部分,但它们都不能工作。
我错过了什么?
更新: 以下解决方案有效,但需要一些黑客攻击。我不敢相信应该需要 str-invoke 中的反射,所以我不会将其发布为答案。
(defn str-invoke [instance method-str & args]
(clojure.lang.Reflector/invokeInstanceMethod
instance
method-str
(to-array args)))
(defn get-sql-metadata
"Take database spec, metadata method (as string) and method parameters"
[db method & args]
(sql/with-connection db
(doall
(resultset-seq
(apply str-invoke
(.getMetaData (sql/connection))
method args)))))
(get-sql-metadata db "getTables" nil nil "%" (into-array '("TABLE")))
问题似乎是需要 apply ,但不能在 .表格。
【问题讨论】: