2012-03-19 3 views
13

Похоже, SQLite не применяет внешние ключи по умолчанию. Я использую sqlitejdbc-v056.jar, и я прочитал, что использование PRAGMA foreign_keys = ON; приведет к ограничениям внешнего ключа и что это необходимо включить для каждого соединения.Как вы применяете ограничения внешнего ключа в SQLite через Java?

Мой вопрос: какие инструкции Java нужно выполнить для включения этой команды? Я пробовал:

connection.createStatement().execute("PRAGMA foreign_keys = ON"); 

и

Properties properties = new Properties(); 
properties.setProperty("PRAGMA foreign_keys", "ON"); 
connection = DriverManager.getConnection("jdbc:sqlite:test.db", properties); 

и

connection = DriverManager.getConnection("jdbc:sqlite:test.db;foreign keys=true;"); 

но ни одна из этих работ. Что-то мне здесь не хватает?

Я видел this answer, и я хочу сделать то же самое, только используя JDBC.

+1

Какую версию SQLite вы используете? (Ограничения внешнего ключа были введены в 3.6.19.) – dan04

+0

3.6.14.2, по-видимому. Даже не осознавал. – Zarjio

ответ

14

Когда вы смотрите на SQLite Foreign Key Support page я бы истолковать, что

  1. SQLlite должен быть собран с поддержкой внешнего ключа
  2. Вы все еще должны включить его для каждого соединения с ПРАГМА
  3. Вы должны определение внешнего ключа в качестве ограничения при создании таблицы

Ad 1) Цитируется из here:

If the command "PRAGMA foreign_keys" returns no data instead of a single row containing "0" or "1", then the version of SQLite you are using does not support foreign keys (either because it is older than 3.6.19 or because it was compiled with SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER defined).

Каков ваш результат для PRAGMA foreign_keys;?

Обновление: от вашего комментария Я вижу, что вы используете 3.6.14.2, это означает, что ваша версия не поддерживает ограничения внешнего ключа! Поэтому вам нужно обновить SQLite, если это возможно!

Объявление 2) Ваш первый фрагмент кода выполняет PRAGMA как утверждение, я не думаю, что это сработает. Третий отрезанный не работал на основе вашего комментария: Драйвер SQLite интерпретирует всю строку как местоположение базы данных, вместо того, чтобы принимать «внешние ключи = истина» в качестве параметров подключения «. Таким образом, только второй фрагмент будет . работа

Ad 3) Знаете ли вы создать таблицу с поддержкой внешнего ключа Цитируется из here?:

CREATE TABLE artist(
    artistid INTEGER PRIMARY KEY, 
    artistname TEXT 
); 
CREATE TABLE track(
    trackid  INTEGER, 
    trackname TEXT, 
    trackartist INTEGER, 
    FOREIGN KEY(trackartist) REFERENCES artist(artistid) 
); 
+0

Да, таблица была создана с поддержкой внешнего ключа. И я должен быстро заметить, что третий метод вообще не работает, драйвер SQLite интерпретирует всю строку как местоположение базы данных, вместо того, чтобы в качестве параметров подключения принимать часть «foreign keys = true». – Zarjio

1

Попробуйте

connection = DriverManager.getConnection("jdbc:sqlite:test.db;foreign keys=true;"); 

Основываясь на вопрос, который вы связаны, это выглядит вероятным кандидатом.

+0

Извините, должен был упомянуть, что я уже пробовал это, и он тоже не работал. – Zarjio

0

Я нашел этот вопрос, а погуглить та же проблема, что я использовал sqlitejdbc-v056.jar из Zentus, который использует. более старой версии драйвера SQLite и не поддерживает внешние ключи.

Я попробовал то, что, кажется, водитель Xerial v3.7.2 из Maven Repository

Я не исследовал различие между этими драйверами, но горячее переключение между ними ничего не сломало и сосредоточил свой вопрос, так , Я надеюсь, что это помогает кому-то.

1

На рабочем столе Linux, когда я пытался,

connection = DriverManager.getConnection("jdbc:sqlite:/path/to/test.db;foreign keys=true;"); 

sqlite3 (3.7.13) считал, что моя база данных файл был /path/to/test.db;foreign ключи = истинные. Это привело к странному, но я предполагаю, что подходящая, ошибку: таблицы не существует

См how to solve no such table while inserting exception in sqlite data base

Я думал, что фиксированный оба этих проблемы, наполняя внешний ключ заявления в собственность, как так:

private final Properties connectionProperties = new Properties(); 
connectionProperties.setProperty("PRAGMA foreign_keys", "ON"); 
private final String connectionString = String.format("jdbc:sqlite:%s", absolute_path_to_sqlite_db); 
Connection connection = DriverManager.getConnection(connectionString, connectionProperties); 

Но даже проблема с именем базы данных была решена, SQLite по-прежнему допускает нарушения ограничений. Некоторые более нудлинг с водителем Xerial и это то, что в конце концов сработало:

private final Properties connectionProperties = new Properties(); 
SQLiteConfig config = new SQLiteConfig(); 
config.enforceForeignKeys(true); 
connectionProperties = config.toProperties(); 
private final String connectionString = String.format("jdbc:sqlite:%s", absolute_path_to_sqlite_db); 
Connection connection = DriverManager.getConnection(connectionString, connectionProperties); 
26

код так:

DriverManager.getConnection("jdbc:sqlite:some.db;foreign keys=true;") 

не работает. Вам необходимо создать org.sqlite.SQLiteConfig и установить его как свойства при вызове getConnection из DriverManager.

public static final String DB_URL = "jdbc:sqlite:database.db"; 
public static final String DRIVER = "org.sqlite.JDBC"; 

public static Connection getConnection() throws ClassNotFoundException { 
    Class.forName(DRIVER); 
    Connection connection = null; 
    try { 
     SQLiteConfig config = new SQLiteConfig(); 
     config.enforceForeignKeys(true); 
     connection = DriverManager.getConnection(DB_URL,config.toProperties()); 
    } catch (SQLException ex) {} 
    return connection; 
} 

Этот код взят из this.

+0

Это работает как шарм!Это снова один из тех ответов, которые должны были быть приняты в качестве ответа. –

+0

Спасибо! Отличный ответ. – noobProgrammer

+0

Отлично, он решил мою проблему. –

4

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

connection.createStatement().execute("PRAGMA foreign_keys = ON"); 

абсолютно делает работу, когда ваша версия SQLite является обновляется и поддерживает поддержку внешнего ключа.

0

Эта страница была полезной при переводе на Clojure, однако мое решение было другим. Так, для потомков, несмотря на то, что ОП просили Java, это, как я сделал это в Clojure:

(def db-spec {:connection-uri "jdbc:sqlite:db.sqlite3?foreign_keys=on;"})

0

Я использую mybatis, в mybatis-config.xml:
<property name="url" value="jdbc:sqlite:example.db?foreign_keys=on;"/>
, что работают для mybatis.

Смежные вопросы