Clojure, как вставить блоб в базу данных? - PullRequest
1 голос
/ 03 сентября 2010

Как вставить большой двоичный объект в базу данных с помощью clojure.contrib.sql?

Я пробовал следующее чтение из файла, но получаю следующее исключение:

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")]) ))

Спасибо.

Ответы [ 3 ]

2 голосов
/ 03 сентября 2010

Мне удалось решить эту проблему путем преобразования 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"))]) )) 
2 голосов
/ 14 августа 2011

Теоретически вы можете использовать любой из методов clojure.contrib.sql / insert- * для вставки большого двоичного объекта, передавая большой двоичный объект в виде байтового массива, java.sql.Blob или объекта java.io.InputStream. На практике это зависит от водителя.

Для многих реализаций JDBC все вышеперечисленное работает должным образом, но если вы используете sqlitejdbc 0.5.6 из Clojars, вы обнаружите, что ваш BLOB-объект приведен к строке с помощью toString (). Все команды clojure.contrib.sql / insert- * выпускаются через clojure.contrib.sql / do-prepare, которое вызывает setObject () для java.sql.PreparedStatement. Реализация sqlitejdbc не обрабатывает setObject () ни для одного из типов данных BLOB-объектов, но по умолчанию приводит их к строке. Вот обходной путь, который позволяет хранить капли в SQLite:

  (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]))))
0 голосов
/ 03 сентября 2010

Я полагаю, что вы точно так же вставите любое другое значение: используйте одно из insert-records, insert-rows или insert-values. E.g.:

(insert-values :mytable [:id :blobcolumn] [42 blob])

Дополнительные примеры: http://github.com/richhickey/clojure-contrib/blob/master/src/test/clojure/clojure/contrib/test_sql.clj

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...