2012-03-19 13 views
13

Sembra che SQLite non imponga chiavi esterne per impostazione predefinita. Sto usando sqlitejdbc-v056.jar e ho letto che usando PRAGMA foreign_keys = ON; si attivano i vincoli di chiave esterna e che questo deve essere attivato in base alla connessione.Come si applicano i vincoli di chiave esterna in SQLite tramite Java?

La mia domanda è: quali istruzioni Java è necessario eseguire per attivare questo comando? Ho provato:

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

e

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

e

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

ma nessuno di quelli di lavoro. C'è qualcosa che mi manca qui?

Ho visto this answer e voglio fare esattamente la stessa cosa, usando solo JDBC.

+1

Quale versione di SQLite stai usando? (I vincoli di chiave esterna sono stati introdotti in 3.6.19.) – dan04

+0

3.6.14.2, apparentemente. Non lo sapevo nemmeno. – Zarjio

risposta

14

Quando si guarda la SQLite Foreign Key Support page vorrei interpretare tale

  1. SqlLite deve essere compilato con il supporto chiave esterna
  2. Hai ancora di accenderlo per ogni connessione con PRAGMA
  3. Devi definire la chiave esterna, come vincolo quando si crea la tabella

annuncio 1) Citato da here:

012.

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).

Qual è il tuo risultato per PRAGMA foreign_keys;?

Aggiornamento: dal tuo commento vedo che stai usando 3.6.14.2, questo significa che la tua versione non supporta i vincoli di chiave esterna! Quindi devi aggiornare SQLite, se possibile!

Annuncio 2) Il primo snippet di codice esegue il PRAGMA come istruzione, non penso che funzionerà. Il terzo ritaglio non ha funzionato in base al tuo commento: il driver SQLite interpreta l'intera stringa come posizione del database, invece di prendere la parte "chiavi esterne = true" come impostazioni di connessione ". Quindi solo il secondo snippet . lavoro

annuncio 3) lo si crea la tabella con il supporto chiave esterna Citato da 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

Sì, la tabella è stata creata con supporto per chiave esterna. E dovrei subito notare che il terzo metodo non funziona affatto, il driver SQLite interpreta l'intera stringa come posizione del database, invece di prendere la parte "foreign keys = true" come impostazioni di connessione. – Zarjio

1

Prova

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

Sulla base della domanda si è collegato, sembra essere un probabile candidato.

+0

Mi dispiace, avrei dovuto dire che l'ho già provato e non ha funzionato neanche. – Zarjio

0

ho trovato questa domanda mentre Googling lo stesso problema che stavo usando sqlitejdbc-v056.jar da Zentus, che utilizza un. versione precedente del driver SQLite e non supporta chiavi esterne.

ho cercato quello che sembra essere il pilota Xerial v3.7.2 dal Maven Repository

non ho studiato la differenza tra questi driver, ma un caldo-switch tra i due non rompere nulla e fisso il mio problema, in modo da , Spero che questo aiuti qualcuno.

1

Su un desktop Linux, quando ho provato,

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

sqlite3 (3.7.13) pensavano che il mio database di file era chiavi /path/to/test.db;foreign = true. Ciò ha portato alla strana, ma credo opportuno, di errore: tabella non esiste

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

Pensavo di aver fissato entrambi questi problemi farcendo la dichiarazione chiave esterna in una proprietà in questo modo:

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

Ma anche se il problema relativo al nome del database è stato risolto, SQLite continua a consentire violazioni dei vincoli. Alcuni più noodling con il driver di Xerial e questo è ciò che alla fine ha funzionato:

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

codice come questo:

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

non funziona. È necessario creare org.sqlite.SQLiteConfig e impostarlo come proprietà quando si chiama getConnection da 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; 
} 

Questo codice preso da this.

+0

Funziona come un fascino!È ancora una di quelle risposte che avrebbero dovuto essere accettate come risposta. –

+0

Grazie! Bella risposta. – noobProgrammer

+0

Perfetto, ha risolto il mio problema. –

4

io purtroppo non posso commentare la risposta del poster precedente, ma come un testa a testa per chiunque altro che può venire di qui, il primo frammento di codice:

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

assolutamente funziona quando la versione di SQLite è aggiornato e supporta il supporto delle chiavi esterne.

0

questa pagina era utile quando si traduceva in Clojure, tuttavia la mia soluzione era diversa. Così, per i posteri, anche se il PO ha chiesto per Java, questo è come ho fatto in Clojure:

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

0

Io uso mybatis, in mybatis-config.xml:
<property name="url" value="jdbc:sqlite:example.db?foreign_keys=on;"/>
che è lavoro per quadro mybatis.

Problemi correlati