如何使用clojure.contrib.sql在数据库中插入blob?
我已尝试从文件中读取以下内容,但我得到了这个例外:
的SQLException: 消息:列类型无效 SQLState:99999 错误代码:17004 java.lang.Exception:事务回滚:列类型无效(repl-1:125)
(clojure.contrib.sql/with-connection
db
(clojure.contrib.sql/transaction
(clojure.contrib.sql/insert-values :test_blob [:blob_id :a_blob] [3 (FileInputStream. "c:/somefile.xls")]) ))
感谢。
答案 0 :(得分:2)
我能够通过将FileInputStream转换为ByteArray来解决这个问题。
(clojure.contrib.sql/with-connection
db
(clojure.contrib.sql/transaction
(clojure.contrib.sql/insert-values :test_blob [:blob_id :a_blob] [3 (to-byte-array(FileInputStream. "c:/somefile.xls"))]) ))
答案 1 :(得分:2)
理论上,您可以使用任何clojure.contrib.sql / insert- *方法插入blob,将blob作为字节数组,java.sql.Blob或java.io.InputStream对象传递。在实践中,它取决于驾驶员。
对于许多JDBC实现,所有上述工作都按预期工作,但如果你使用Clojars的sqlitejdbc 0.5.6,你会发现你的blob通过toString()强制转换为字符串。所有clojure.contrib.sql / insert- *命令都是通过clojure.contrib.sql / do-prepared发出的,它在java.sql.PreparedStatement上调用setObject()。 sqlitejdbc实现不处理任何blob数据类型的setObject(),但默认情况下将它们强制转换为字符串。这是一个解决方法,使您可以在SQLite中存储blob:
(use '[clojure.contrib.io :only (input-stream to-byte-array)])
(require '[clojure.contrib.sql :as sql])
(defn my-do-prepared
"Executes an (optionally parameterized) SQL prepared statement on the
open database connection. Each param-group is a seq of values for all of
the parameters. This is a modified version of clojure.contrib.sql/do-prepared
with special handling of byte arrays."
[sql & param-groups]
(with-open [stmt (.prepareStatement (sql/connection) sql)]
(doseq [param-group param-groups]
(doseq [[index value] (map vector (iterate inc 1) param-group)]
(if (= (class value) (class (to-byte-array "")))
(.setBytes stmt index value)
(.setObject stmt index value)))
(.addBatch stmt))
(sql/transaction
(seq (.executeBatch stmt)))))
(defn my-load-blob [filename]
(let [blob (to-byte-array (input-stream filename))]
(sql/with-connection db
(my-do-prepared "insert into mytable (blob_column) values (?)" [blob]))))
答案 2 :(得分:0)
我相信它与您插入任何其他值的方式相同:使用insert-records
,insert-rows
或insert-values
之一。 E.g:
(insert-values :mytable [:id :blobcolumn] [42 blob])
答案 3 :(得分:0)
对此线程的最新回复还包括读取数据的代码:
(ns com.my-items.polypheme.db.demo
(:require
[clojure.java.io :as io]
[clojure.java.jdbc :as sql]))
(def db {:dbtype "postgresql"
:dbname "my_db_name"
:host "my_server"
:user "user",
:password "user"})
(defn file->bytes [file]
(with-open [xin (io/input-stream file)
xout (java.io.ByteArrayOutputStream.)]
(io/copy xin xout)
(.toByteArray xout)))
(defn insert-image [db-config file]
(let [bytes (file->bytes file)]
(sql/with-db-transaction [conn db-config]
(sql/insert! conn :image {:name (.getName file) :data bytes}))))
(insert-image db (io/file "resources" "my_nice_picture.JPG"))
;;read data
(defn read-image [db-config id]
(-> (sql/get-by-id db-config :image id)
:data
(#(new java.io.ByteArrayInputStream %))))