我正在开发一个程序,将USDA营养数据库文件从ASCII转换为sqlite数据库。有关这些文件的信息可以在http://www.ars.usda.gov/Services/docs.htm?docid=8964找到,相当于非常棒的东西。
但是,在下面的代码中,只要我在执行转换的函数中输入for构造,我的sql连接就“消失”。
(defn sanitize-field [field]
(cond
(= field "~~") ""
(= field "") 0
(and (.startsWith field "~") (.endsWith field "~"))
(.substring field 1 (- (.length field) 1))
:default (try
(Double. field)
(catch NumberFormatException n 0.0))))
(defn field-separator [line]
(.split line "\\^"))
(defn parse-file [file]
(map (fn [l] (map sanitize-field (field-separator l)))
(.split (slurp (.getCanonicalPath file)) "\r\n")))
(defn convert-food-description [source-dir]
(println (sql/connection))
(for [entry (parse-file (File. source-dir "FOOD_DES.txt"))]
(do
(println entry)
(println (sql/connection))
(sql/insert-rows "food_des" entry))))
(Class/forName "org.sqlite.JDBC")
(def db {:classname "com.sqlite.JDBC" :subprotocol "sqlite" :subname "nutrition.sqlite"})
(defn convert []
(sql/with-connection db
(convert-food-description (File. "/home/savanni/Downloads/nutrient_database"))))
当我运行转换操作时,我得到的是:
user=> (convert)
(convert)
#<Conn org.sqlite.Conn@180e426>
((01001 0100 Butter, salted BUTTER,WITH SALT Y 0.0 6.38 4.27 8.79 3.87)
java.lang.Exception: no current database connection
所以,我唯一的println命令是转换食物描述。在函数开始执行正常后,它看起来像第一个,打印出我用with-connection语句创建的连接。但是,然后for循环开始,我打印出我要插入数据库的第一行数据,然后在尝试再次打印SQL连接时抛出异常。
什么可能导致连接在那里消失?还有其他事情发生了吗?
更新:这里的sql / functions都来自clojure.contrib.sql
答案 0 :(得分:3)
for
很懒。在with-connection
for
进行评估之前,convert-food-description
正在打开和关闭您的连接句柄。
您必须在连接句柄仍处于活动状态时强制进行评估。例如,尝试将for
更改为doseq
。
user> (require '(clojure.contrib [sql :as sql]))
nil
user> (import 'org.sqlite.JDBC)
org.sqlite.JDBC
user> (def db {:classname "com.sqlite.JDBC"
:subprotocol "sqlite"
:subname "foo.sqlite"})
#'user/db
user> (sql/with-connection db (sql/create-table "foo" ["val" "int"]))
(0)
;; Bad
user> (defn foo []
(sql/with-connection db
(for [x (range 10)]
(sql/insert-records "foo" {:val x}))))
#'user/foo
user> (foo)
; Evaluation aborted.
;;java.lang.Exception: no current database connection
;; Good
user> (defn foo []
(sql/with-connection db
(doseq [x (range 10)]
(sql/insert-rows "foo" [x]))))
#'user/foo
user> (foo)
nil
答案 1 :(得分:0)
首先,您的(println (sql/connection))
未打印当前连接。而是创建新的并打印它。
其次,您已将db定义为(def db {:classname "com.sqlite.JDBC" :subprotocol "sqlite" :subname "nutrition.sqlite"})
这不会打开连接,这只是一个连接描述。
第三,您应该将db
作为参数传递给convert-food-description
方法,并将其用于实际查询。