Как вы применяете ограничения внешнего ключа в SQLite через Java? - PullRequest
15 голосов
/ 19 марта 2012

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

Мой вопрос: какие операторы 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;");

но ничего из этого не работает. Я что-то упускаю здесь?

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

Ответы [ 8 ]

31 голосов
/ 14 ноября 2012

Код такой:

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;  
}

Этот код взят из этого .

16 голосов
/ 23 марта 2012

Когда вы смотрите на страницу поддержки внешнего ключа SQLite , я бы интерпретировал это

  1. SQLlite должен быть скомпилирован с поддержкой внешнего ключа
  2. Вы все равно должны включать его для каждого соединения с PRAGMA
  3. Вы должны определить внешний ключ как ограничение при создании таблицы

Объявление 1) Цитируется здесь :

Если команда «PRAGMA foreign_keys» не возвращает данных вместо одной строки, содержащей «0» или «1», то используемая вами версия SQLite не поддерживает внешние ключи (так как старше 3.6.19 или потому что он был скомпилирован с SQLITE_OMIT_FOREIGN_KEY или SQLITE_OMIT_TRIGGER с определением ).

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

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

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

Объявление 3) Вы создали таблицу с поддержкой внешних ключей? Цитируется здесь :

CREATE TABLE artist(
  artistid    INTEGER PRIMARY KEY, 
  artistname  TEXT
);
CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
4 голосов
/ 27 июня 2014

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

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

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

1 голос
/ 22 декабря 2016

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

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

1 голос
/ 16 августа 2012

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

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

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

См. , как решить проблему отсутствия такой таблицы при вставке исключения в базу данных sqlite

Я думал, что исправил обе эти проблемы, вставив выражение внешнего ключа в свойство, подобное следующему:

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);
1 голос
/ 19 марта 2012

Попробуйте

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

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

0 голосов
/ 07 марта 2018

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

0 голосов
/ 20 мая 2012

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

Я пытался использовать драйвер Xerial v3.7.2 из репозитория Maven

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...