Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java方法作为带有嵌套方法调用的函数中的参数(更新)_Java_Sql_Jdbc_Clojure - Fatal编程技术网

Java方法作为带有嵌套方法调用的函数中的参数(更新)

Java方法作为带有嵌套方法调用的函数中的参数(更新),java,sql,jdbc,clojure,Java,Sql,Jdbc,Clojure,我有一个通过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.sqlser

我有一个通过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)
现在,我想通过将java方法调用包装在clojure函数中作为参数,扩展该函数以使用其他SQL元数据,如下所示:

(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、…、>和(.notation)重写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,但不能在.form上使用。

问题是您试图在对象“nil”上调用.getTables。当您删除(.getMetaData(sql/connection))时您删除了.getTables消息的接收者。您需要元数据对象,以便可以对其调用.getTables方法。您可以将其包装在let中:

(let [metadata (.getMetaData (sql/connection))]
  (get-sql-metadata db #(.getTables metatdata nil nil "%" (into-array '("TABLE")))))
更新:

这个怎么样:

(get-sql-metadata db (fn [meta] (.getTables meta nil nil "%" (into-array '("TABLE")))))
然后“获取表元数据”变为:

(defn get-table-metadata
  "Take database spec, return all table names from the database metadata"
  [db metafunction]
  (sql/with-connection db
    (doall
     (resultset-seq
      (metafunction (.getMetaData (sql/connection)))))))

在生成get sql元数据时,函数将导致clojure在应用函数之前对参数求值,因此无法向函数传递无法求值的“.unknown”符号,如.getTables

另一方面,在宏中,在应用宏之前不会计算参数。 因此,将函数设置为宏将允许您执行此操作

比如:


当然也有可能通过使用宏memfn将方法调用转换为clojure函数,但我认为这不是您想要的

那样我仍然可以传递(.getMetaData(sql/connection))在函数参数中,只是以不同的形式。也许我应该重写这个问题,但我正在寻找一种方法,如何在get sql metadata函数中抽象它(在resultset seq中),只将db&the.getTables方法及其参数放在函数参数中。解决方案可行,但函数参数很难变得更清晰或更简洁。我自己找到了一个解决方案,我将在更新中发布,但我不相信它使用的反射步骤是必要的。
(defmacro get-sql-metadata [db method & args] 
  `(with-connection 
    ~db 
    (doall 
      (resultset-seq 
        (~method 
          (.getMetaData (connection)) 
          ~@args)))))