위키 프로그램에서 SQLite를 데이터베이스로 사용하고 있습니다. 위키 페이지와 그 페이지를 설명하는 태그 사이에 다 대다 관계를 만들고 싶습니다. 데이터베이스 작업을 처리하기 위해 clojure.java.jdbc
을 사용하고 있습니다. 페이지 - 투 - 태그 상호 참조 테이블에 외래 키 제약 조건을 적용하고 싶습니다. 나는 SQLite 사이트 (https://www.sqlite.org/foreignkeys.html)에서 외래 키에 대한 정보를보고, 내가 좋아하는 것이 무엇인지 믿는다;clojure.java.jdbc와 Clojure의 외래 키 제약 조건 사용
(def the-db-name "the.db")
(def the-db {:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname the-db-name})
(defn create-some-tables
"Create some tables and a cross-reference table with foreign key constraints."
[]
(try (jdbc/db-do-commands
the-db false
["PRAGMA foreign_keys = ON;"
(jdbc/create-table-ddl :pages
[[:page_id :integer :primary :key]
;...
[:page_content :text]])
(jdbc/create-table-ddl :tags
[[:tag_id :integer :primary :key]
[:tag_name :text "NOT NULL"]])
(jdbc/create-table-ddl :tags_x_pages
[[:x_ref_id :integer :primary :key]
[:tag_id :integer]
[:page_id :integer]
["FOREIGN KEY(tag_id) REFERENCES tags(tag_id)"]
["FOREIGN KEY(page_id) REFERENCES pages(page_id)"]])])
(catch Exception e (println e))))
그러나 플러그 - 마를 켜려고해도 아무 효과가 없습니다.
(println "Check before:" (jdbc/query the-db ["PRAGMA foreign_keys;"]))
; Transactions on or off makes no difference.
(println "Result of execute!:" (jdbc/execute! the-db
["PRAGMA foreign_keys = ON;"]))
(println "Check after:" (jdbc/query the-db ["PRAGMA foreign_keys;"]))
;=> Check before: ({:foreign_keys 0})
;=> Result of execute!: [0]
;=> Check after: ({:foreign_keys 0})
결과는 라이브러리 (org.xerial/SQLite는-JDBC "3.21.0.1") 이후 외래 키를 지원하기 위해 컴파일 된 것을 나타냅니다
그냥에 프라그를 켜고 효과를 확인하기 위해 노력하고 오류는 없었지만 pragma를 설정하려고해도 아무런 효과가 없습니다.2012 년에 클로저 JDBC에 대한 JIRA에서 this을 발견했습니다. 그 이후로 설명 된 변경 사항이 구현되었지만 코드는 여전히 효과가 없습니다.
마지막으로 2011 년에 this post을 가리키는 Stackoverflow 질문에 대한이 대답을 발견했습니다. 그 덕분에 나는 프 래그 마를 설정하는 것처럼 보이는 것을 함께 자갈 할 수있었습니다. 아래 코드는 특별히 구성된 Connection
을 만드는 방법에 따라 다릅니다. 예상대로
(defn create-some-tables
"Create some tables and a cross-reference table with foreign key constraints."
[]
(when-let [conn (get-connection the-db)]
(try
(jdbc/with-db-connection
[conn the-db]
; Creating the tables with the foreign key constraints works.
(try (jdbc/db-do-commands
the-db false
[(jdbc/create-table-ddl :pages
[[:page_id :integer :primary :key]
[:page_content :text]])
(jdbc/create-table-ddl :tags
[[:tag_id :integer :primary :key]
[:tag_name :text "NOT NULL"]])
(jdbc/create-table-ddl :tags_x_pages
[[:x_ref_id :integer :primary :key]
[:tag_id :integer]
[:page_id :integer]
["FOREIGN KEY(tag_id) REFERENCES tags(tag_id)"]
["FOREIGN KEY(page_id) REFERENCES pages(page_id)"]])])
; This still doesn't work.
(println "After table creation:"
(jdbc/query the-db "PRAGMA foreign_keys;"))
(catch Exception e (println e))))
; This returns the expected results.
(when-let [statement (.createStatement conn)]
(try
(println "After creating some tables: PRAGMA foreign_keys =>"
(.execute statement "PRAGMA foreign_keys;"))
(catch Exception e (println e))
(finally (when statement
(.close statement)))))
(catch Exception e (println e))
(finally (when conn
(.close conn))))))
테이블이 만들어집니다 상기 내용을 토대로
(ns example
(:require [clojure.java.jdbc :as jdbc])
(:import (java.sql Connection DriverManager)
(org.sqlite SQLiteConfig)))
(def the-db-name "the.db")
(def the-db {:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname the-db-name})
(defn ^Connection get-connection
"Return a connection to a SQLite database that
enforces foreign key constraints."
[db]
(Class/forName (:classname db))
(let [config (SQLiteConfig.)]
(.enforceForeignKeys config true)
(let [connection (DriverManager/getConnection
(str "jdbc:sqlite:" (:subname db))
(.toProperties config))]
connection)))
(defn exec-foreign-keys-pragma-statement
[db]
(let [con ^Connection (get-connection db)
statement (.createStatement con)]
(println "exec-foreign-keys-pragma-statement:"
(.execute statement "PRAGMA foreign_keys;"))))
, 나는대로 위의 테이블 작성 코드를 다시 썼다.
clojure.java.jdbc
함수 중 일부는 여전히 원하는대로 작동하지 않습니다. (목록의 중간에있는
jdbc/query
호출을 참조하십시오.) 항상 예상대로 작동하도록하는 것이 매우 "수동"인 것으로 자바 interop에서 실패하는 것처럼 보입니다. 그리고 데이터베이스와의 모든 상호 작용이 특별히 구성된
Connection
을 사용하여 수행해야하는 것처럼 보입니다.
get-connection
함수가 반환했습니다.
Clojure에서 SQLite에 외래 키 제약 조건을 적용하는 더 좋은 방법이 있습니까?
그런데 지난 5-6 년 동안'(Class/forName (: classname db))'는 불필요했습니다. – DodgyCodeException