Программа Clojure не работает после компиляции - PullRequest
0 голосов
/ 13 ноября 2010

У меня есть простая программа Clojure, которая запрашивает базу данных Oracle и выводит результаты в формате с разделителями-запятыми. Эта программа прекрасно работает, выполняя ее нормально через Clojure.main. Я хочу скомпилировать эту программу и следуйте инструкциям здесь:

http://java.ociweb.com/mark/clojure/article.html#Compiling

Я скомпилировал и запустил другую простую программу, используя этот метод, описанный просто отлично. Так что я не думаю, что это имеет какое-либо отношение к этому методу компиляции. Эта программа компилируется просто отлично, но когда я пытаюсь запустить скомпилированный класс, она возвращает эту ошибку:

Исключение в теме "главная" java.lang.RuntimeException: java.lang.RuntimeException: java.sql.SQLException: исчерпан Resultset at clojure.lang.LazySeq.sval (LazySeq.java:47) at clojure.lang.LazySeq.seq (LazySeq.java:56) at clojure.lang.RT.seq (RT.java:440) в clojure.core $ seq__4245.invoke (core.clj: 105) в bill.myquery $ dump_db_csv__24.invoke (myquery.clj: 27) в bill.myquery $ main _49.invoke (myquery.clj: 41) at clojure.lang.AFn.applyToHelper (AFn.java:171) at clojure.lang.AFn.applyTo (AFn.java:164) at bill.myquery.main (неизвестный источник) Вызывается: java.lang.RuntimeException: java.sql.SQLException: исчерпан Resultset at clojure.lang.LazySeq.sval (LazySeq.java:47) at clojure.lang.LazySeq.seq (LazySeq.java:56) на clojure.lang.Cons.next (Cons.java:37) at clojure.lang.RT.boundedLength (RT.java:1128) at clojure.lang.RestFn.applyTo (RestFn.java:135) в clojure.core $ apply__4370.invoke (core.clj: 438) в clojure.core $ resultset_seq_ 6276 $ thisfn _6290 $ fn__6291.invoke (core.clj: 3842) at clojure.lang.LazySeq.sval (LazySeq.java:42) ... еще 8 причин: java.sql.SQLException: Exhausted Resultset в oracle.jdbc.driver.DatabaseError.throwSqlException (DatabaseError.java:112) в oracle.jdbc.driver.DatabaseError.throwSqlException (DatabaseError.java:146) в oracle.jdbc.driver.DatabaseError.throwSqlException (DatabaseError.java:208) в oracle.jdbc.driver.OracleResultSetImpl.getObject (OracleResultSetImpl.java:900) в clojure.core $ resultset_seq__6276 $ row_values_ 6284 $ fn _6286.invoke (core.clj: 3839) в clojure.core $ map_ 5053 $ fn _5055.invoke (core.clj: 1760) at clojure.lang.LazySeq.sval (LazySeq.java:42)

Вот оно:

(ns bill.myquery (:gen-class))

;; Import java.sql classes
(import '(java.sql DriverManager Connection PreparedStatement ResultSet))

;; load jdbc/odbc driver
(. Class forName "oracle.jdbc.driver.OracleDriver")

(def dbname "myOracleServer:1522:myOracleDatabase")
(def service_account "account")
(def service_password "password")

(def conn (. DriverManager (getConnection (str "jdbc:oracle:thin:@" dbname) service_account service_password)))

(def sql "
        SELECT name, address, phone
        FROM addresss_book
        ORDER BY name")

;; Function to dump data with comma delimited fields
(defn dump-db-csv [db]
  (doseq [rec db] ;; for all rows
    (doseq [[key value] rec] ;; for all fields
        (if (= key :phone) ;; if last field
              (print (.trim (str value))) ;; don't print comma
              (print (format "%s%s" (.trim (str value)) ","))))
    (println)))

;; Execute query and get recordset
(def rs (.. conn (prepareStatement sql) (executeQuery)))

;; convert recordset to sequence
(def rset (resultset-seq rs))

;; Main call the function to print rows
(defn -main (dump-db-csv rset))

;; close the recordset
(. rs (close))

Ответы [ 2 ]

3 голосов
/ 13 ноября 2010

Не используйте def - все с верхнего уровня выполняется во время загрузки класса (или даже во время компиляции), поэтому вы закрываете набор результатов (rs) перед запуском -main. Всегда открывайте и закрывайте соединение в одной функции - это предотвратит множество ошибок.

Также рассмотрите возможность использования clojure.contrib.sql . Хорошие примеры можно найти в wikibooks .

Для обоих методов не забудьте использовать doall для любых возможных ленивых последовательностей.

0 голосов
/ 13 ноября 2010

Я воспользовался советом Андрея и использовал clojure.contrib.sql. Это делает это еще более простым и менее подверженным ошибкам. Я все еще не хотел отказываться от def для глобальных переменных db и sql.

Спасибо, Андрей

(ns my.query (:use [clojure.contrib.sql]))

(def *db* {:classname "oracle.jdbc.driver.OracleDriver" ; must be in classpath
           :subprotocol "oracle:thin"
           :subname "myserver:1521:mydatabase"
           ; Any additional keys are passed to the driver
           ; as driver-specific properties.
           :user "account"
           :password "password" })

(def *sql* "select * from phonebook")

(defn dump-db-csv []
  (with-connection *db*
    (transaction
      (with-query-results rs [*sql*]
          (doseq [row rs] ;; for all rows
            (doseq [[key value] row] ;; for all fields
                (if (= key :phone) ;; if last field
                  (print (.trim (str value))) ;; do not print comma
                  (print (format "%s%s" (.trim (str value)) ","))))
            (println))))))

;; Main - call the function to print rows
(dump-db-csv)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...