本章源代碼: https://github.com/LightSwordSpringBoot/clj-webhtml
##訪問數據庫java
Java 提供了標準的 JDBC 接口訪問數據庫,Clojure 的數據庫接口mysql
clojure.java.jdbc
是對 Java JDBC 的封裝。咱們只須要引用 clojure.java.jdbc 以及對應的數據庫驅動,就能夠在 Clojure 代碼中訪問數據庫。git
clojure.java.jdbc 是一個比較底層的接口。咱們使用 DSL 的模式來編寫數據庫代碼,相似 Java 的 Hibernate,選擇 Korma 來編寫訪問數據庫的代碼。github
因爲 Clojure 是 Lisp 方言,它繼承了 Lisp 強大的「代碼即數據」的功能,在 Clojure 代碼中,編寫 SQL 語句對應的 DSL 十分天然,徹底無需 Hibernate 複雜的映射配置。web
咱們先配置好 MySQL 數據庫,而後建立一個表來測試 Clojure 代碼.sql
建立 schema數據庫
CREATE SCHEMA `cljweb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
建立表eclipse
create table courses ( `id` varchar(32) not null primary key, `name` varchar(50) not null, `price` real not null, `online` bool not null, `days` bigint not null );
新建一個 db.clj 文件,選擇菜單「File」-「New」-「Other...」,選擇「Clojure」-「Clojure Namespace」,填入名稱ide
course.db
就能夠建立一個 db.clj 文件。
在編寫代碼前,咱們首先要在 project.clj 文件中添加依賴項。
[org.clojure/java.jdbc "0.3.6"] [mysql/mysql-connector-java "5.1.25"] [korma "0.3.0"]
咱們執行
lein pom
能夠發現新生成的 pom.xml, 添加了新的依賴:
<dependencies> <dependency> <groupId>org.clojure</groupId> <artifactId>clojure</artifactId> <version>1.8.0</version> </dependency> <dependency> <groupId>org.clojure</groupId> <artifactId>java.jdbc</artifactId> <version>0.3.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency> <dependency> <groupId>korma</groupId> <artifactId>korma</artifactId> <version>0.3.0</version> </dependency> </dependencies>
使用 Korma 操做數據庫十分簡單,只須要先引用 Korma。
(ns ^{:author jack} org.lightsword.course.db (:use korma.db korma.core) )
定義數據庫鏈接
(defdb korma-db (mysql { :db "cljweb", :host "localhost", :port 3306, :user "root", :password "root" }))
而後定義一下要使用的 entity,也就是表名。
定義 entity
(declare courses) (defentity courses)
如今,就能夠對數據庫進行操做了。插入一條記錄。
執行 insert
(insert courses (values {:id "007", :name "Clojure Programming", :price 45.8, :online true, :days 30}) )
使用 Clojure 內置的 map 類型,十分直觀。
查詢語句經過 select 宏實現了 SQL DSL 到 Clojure 代碼的天然映射。 執行 select
(select courses (where {:online true}) (order :name :asc) )
這徹底得益於 Lisp 的 S 表達式的威力,既不須要直接拼湊 SQL,也不須要從新發明相似 HQL 的語法。
利用 Korma 提供的 sql-only 和 dry-run,能夠打印出生成的 SQL 語句.
(ns org.lightsword.course.db (:use korma.db korma.core)) (defdb korma-db (mysql { :db "cljweb", :host "localhost", :port 3306, :user "root", :password "root" })) (declare courses) (defentity courses) (defn create-course! [c] (println "create course:" c) (insert courses (values c) ) ) (defn get-courses [] (select courses (where {:online true}) (order :name :asc) ) ) (defn get-all [] (select courses (order :name :asc)) ) (defn init-courses! [] (if (empty? (get-courses)) (let [cs [{:id "s-201", :name "SQL", :price 99.9, :online false, :days 30 }, {:id "s-202", :name "PHP", :price 69.9, :online false, :days 15}, {:id "s-203", :name "F#", :price 80.0, :online false, :days 20}]] (println "init courses ...") (dorun (map create-course! cs)) ) ) ) (defn -main [& args] (init-courses!) (println (get-courses)) (println (get-all)) )
咱們配置一下 main
project.clj
(defproject org.lightsword/clj-web "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :main org.lightsword.course.db :dependencies [[org.clojure/clojure "1.8.0"] [org.clojure/java.jdbc "0.3.6"] [mysql/mysql-connector-java "5.1.25"] [korma "0.3.0"] ])
運行
$ lein run WARNING: update already refers to: #'clojure.core/update in namespace: korma.core, being replaced by: #'korma.core/update WARNING: update already refers to: #'clojure.core/update in namespace: org.lightsword.course.db, being replaced by: #'korma.core/update 七月 03, 2016 1:19:55 下午 com.mchange.v2.log.MLog <clinit> 信息: MLog clients using java 1.4+ standard logging. 七月 03, 2016 1:19:55 下午 com.mchange.v2.c3p0.C3P0Registry banner 信息: Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10] 七月 03, 2016 1:19:55 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager 信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hge1619h1cm0f3t1s80nsr|d1f74b8, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge1619h1cm0f3t1s80nsr|d1f74b8, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/cljweb, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 10800, maxIdleTimeExcessConnections -> 1800, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ] [{:id 007, :name Clojure Programming, :price 45.8, :online true, :days 30}] [{:id 007, :name Clojure Programming, :price 45.8, :online true, :days 30} {:id s-203, :name F#, :price 80.0, :online false, :days 20} {:id s-202, :name PHP, :price 69.9, :online false, :days 15} {:id s-201, :name SQL, :price 99.9, :online false, :days 30}]
從運行日誌咱們能夠看出, org.clojure/java.jdbc 底層調用的是
driverClass -> com.mysql.jdbc.Driver