2010-07-01 5 views
4

Я пишу приложение Compojure TODO и MySQL в качестве основного хранилища данных. Я использую clojure.contrib.sql для взаимодействия с MySQL следующим образом:Compojure + clojure.contrib.sql: запрос SELECT кэшируется. Зачем?

(def db {:classname "com.mysql.jdbc.Driver" 
     :subprotocol "mysql" 
     :subname "//localhost:3306/todo" 
     :user "<user>" 
     :password ""}) 

Запросов я использую, кажется, работает, однако результаты появляются в кэше. Например, после запуска

(with-connection db 
    (insert-values :todos 
    [:name] [name])) 

значение успешно вставлено в базу данных. Однако

(defn sql-query [query] 
    (with-connection db 
    (with-query-results rows [query] 
     (into [] rows)))) 

возвращает то же значение, независимо от количества вставленных элементов. Конечно, если я перезапущу веб-приложение, результаты будут обновлены, но это не очень удобно для работы с продуктом :).

Любая идея, почему это происходит? Заранее спасибо.

В соответствии с просьбой, вот форма верхнего уровня для запроса на выборку:

(def home-view 
    (render 
    (base {:title "Clojure Todo" 
      :content (apply str 
      (map #(% :name) 
       (sql-query "select * from todos")))}))) 
+0

Это похоже на то, как SQL Server кэширует планы выполнения запросов, которые запускаются с целью повышения производительности для базы данных, предотвращая оптимизацию запросов каждый раз, когда они выполняются. – 2010-07-01 23:17:03

+0

Посмотрите эту статью, чтобы узнать о кешировании запросов в MySQL: http://www.databasejournal.com/features/mysql/article.php/3110171/MySQLs-Query-Cache.htm Это может быть причиной. BTW, то, что кэшируется, является фактическим набором результатов; кэширование только плана выполнения не повлияет на правильность возвращенных результатов. –

+0

Я не думаю, что это имеет ничего общего с MySQL, я думаю, что это проблема Clojure. –

ответ

3

От последнего добавленного комментария на ответ вместе с последним обновлением к тексту вопроса я понял, что проблема не имеет отношения к clojure.contrib.sql, это форма defroutes.

(defroutes todo (GET "/" [] home-view)) означает, что запросы, соответствующие этому маршруту, будут получать home-view в виде ответа. Теперь home-view оценивается только один раз, когда форма (def home-view ...) оценивается - и, в частности, связанный SQL-запрос выполняется только один раз.

Чтобы это исправить, переписать home-view как функция и есть маршрут назвать это, возможно, например, так:

(defn home-view [] 
    ...the render form from your old (def home-view ...) form goes here... 
) 

(defroutes todo (GET "/" [] (home-view))) 

home-view Тогда -The-функция будет вызываться каждый раз, когда маршрут получает срабатывает (и выполнить его SQL-запрос один раз для каждого такого вызова).

+0

Ты прибил его. Спасибо за вашу помощь! –