Исключение UCanAccess при открытом соединении - в столбцах, на которые есть ссылки, отсутствует уникальное ограничение - PullRequest
0 голосов
/ 29 января 2020

Я пытаюсь создать очень простое соединение с базой данных доступа (.accdb) в моем java проекте maven с использованием ucanaccess. База данных является внешней базой данных, и мне просто нужно прочитать содержимое некоторых таблиц для задачи миграции. Я не хочу и не должен изменять таблицы или записывать что-либо в базу данных. Код java, который я использовал, очень прост:

try (Connection connection = DriverManager.getConnection(databaseURL);) {
} catch (SQLException ex) { ex.printStackTrace(); }

Но вначале происходит сбой соединения со следующим исключением:

net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::5.0.0 a UNIQUE constraint does not exist on referenced columns: T1 in statement [ALTER TABLE T2 ADD CONSTRAINT "T2{2EB41B92-C3AB-4A64-A53C-B83095D76202}" FOREIGN KEY  (C2)  REFERENCES T1 (C1) ]
    at net.ucanaccess.jdbc.UcanaccessDriver.connect(UcanaccessDriver.java:231)
    at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
    at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)
    at myproject.Application.main(Application.java:42)
Caused by: java.sql.SQLSyntaxErrorException: a UNIQUE constraint does not exist on referenced columns: T1 in statement [ALTER TABLE T2 ADD CONSTRAINT "T2{2EB41B92-C3AB-4A64-A53C-B83095D76202}" FOREIGN KEY  (C2)  REFERENCES T1 (C1) ]
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCStatement.fetchResult(Unknown Source)
    at org.hsqldb.jdbc.JDBCStatement.executeUpdate(Unknown Source)
    at net.ucanaccess.converters.LoadJet.exec(LoadJet.java:1510)
    at net.ucanaccess.converters.LoadJet.access$000(LoadJet.java:74)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadForeignKey(LoadJet.java:695)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTableFKs(LoadJet.java:918)
    at net.ucanaccess.converters.LoadJet$TablesLoader.recreate(LoadJet.java:807)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTableData(LoadJet.java:877)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTableData(LoadJet.java:871)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTableData(LoadJet.java:837)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTablesData(LoadJet.java:1029)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTables(LoadJet.java:1077)
    at net.ucanaccess.converters.LoadJet$TablesLoader.access$3200(LoadJet.java:264)
    at net.ucanaccess.converters.LoadJet.loadDB(LoadJet.java:1579)
    at net.ucanaccess.jdbc.UcanaccessDriver.connect(UcanaccessDriver.java:218)
    ... 3 more
Caused by: org.hsqldb.HsqlException: a UNIQUE constraint does not exist on referenced columns: T1
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.TableWorks.checkCreateForeignKey(Unknown Source)
    at org.hsqldb.TableWorks.addForeignKey(Unknown Source)
    at org.hsqldb.StatementSchema.getResult(Unknown Source)
    at org.hsqldb.StatementSchema.execute(Unknown Source)
    at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
    at org.hsqldb.Session.executeDirectStatement(Unknown Source)
    at org.hsqldb.Session.execute(Unknown Source)
    ... 18 more

Я попытался установить соединение «только для чтения», так что он не проверяет это ограничение и не выдает исключение. Но я не добился успеха.

try (Connection connection = DriverManager.getConnection(databaseURL + ";readonly=true");) {
} catch (SQLException ex) { ex.printStackTrace(); } 

Есть ли способ отключить эту проверку ограничений при создании соединения для чтения некоторых таблиц?

1 Ответ

0 голосов
/ 05 февраля 2020

Я не могу опубликовать базу данных для воспроизведения проблемы! Потому что это очень сложная база данных с множеством таблиц и связей, и она не принадлежит мне. Мне не разрешено делиться этим (даже без данных) из-за Общих правил защиты данных.

Кроме того, я не хотел ничего менять в базе данных, поэтому я хотел отключить проверки ограничений, чтобы иметь возможность просто подключиться к базе данных и просто ПРОЧИТАТЬ строки некоторых таблиц.

В конце я сделал копию базы данных и удалил все связи между таблицами, а затем код мог подключиться к БД, НО : УТОЧНУЛО 30 МИНУТ ДЛЯ ПОДКЛЮЧЕНИЯ !!!! Таким образом, даже если бы мне удалось сделать копию из базы данных и удалить все связи между всеми таблицами каждый раз, когда я хочу запустить свой код (что на самом деле невозможно в моей задаче), я должен был ждать 30 минут, чтобы просто открой соединение !!! Я нахожу действительно смешным, что нет возможности отключить проверки ограничений и открыть соединение для чтения данных, когда некоторые ограничения не выполняются !!!

Но в любом случае, в конце (после двух дни в поисках!) я нашел решение для своей работы. Я не использую какой-либо тип соединения DriverManager этого типа:

Connection connection = DriverManager.getConnection(databaseURL)

Вместо этого я использую DatabaseBuilder, чтобы открыть свою базу данных, получить таблицы и прочитать строки! Для тех, кто имеет такую ​​же проблему и просто хочет подключиться к базе данных MS-Access, чтобы ПРОЧИТАТЬ некоторые данные, ничего не меняя, я предлагаю этот способ. Это очень просто и быстро!

String fileName = "my_database.accdb";
File file = new File(fileName);
Database db = null;
DatabaseBuilder databaseBuilder = new DatabaseBuilder(file);
try {
     db = databaseBuilder.open();
} catch(IOException e) {
     e.printStackTrace();
}
Table myTable = db.getTable("myAccessTableName");
for(Row row : myTable) {
     String firstName = row.getString("first_name");
     String lastName = row.getString("last_name");
}

База данных, DatabaseBuilder, Row и Table из "jackcess". Таким образом, этот импорт необходим:

import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.Row;
import com.healthmarketscience.jackcess.Table;

Дополнительные примеры использования этого способа можно найти здесь: Java Примеры кода и здесь: UCanAccess

...