Я использую H2 для проверки кода моей базы данных. Для этого я начинаю с чтения в наборе файлов SQL и используя RunScript.execute
для выполнения SQL.
Моя реальная база данных - это MySQL, и я протестировал SQL-скрипты, чтобы убедиться, что они работают, и они это делают. Проблема явно внутри H2. Здесь набор скриптов:
CREATE TABLE stores (
id integer AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NOT NULL,
UNIQUE(name),
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at timestamp
);
CREATE TABLE regions (
id integer AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NOT NULL,
UNIQUE(name),
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at timestamp
);
CREATE TABLE products (
id integer AUTO_INCREMENT PRIMARY KEY,
store_id integer NOT NULL,
name varchar(255) NOT NULL,
region_id integer NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at timestamp,
UNIQUE(store_id, name),
FOREIGN KEY store_fk(store_id) REFERENCES stores(id),
FOREIGN KEY region_fk(region_id) REFERENCES regions(id)
);
Запуск этих 3 скриптов для создания таблиц с использованием MySQL Workbench отлично работает. Запуск их из JUnit с помощью следующего кода:
Reader storeTableSql = new InputStreamReader(
DatabaseConnectorTests.class.getResourceAsStream(
"/migrations/V1__create_stores_table.sql"));
Reader regionTableSql = new InputStreamReader(
DatabaseConnectorTests.class.getResourceAsStream(
"/migrations/V2__create_regions_table.sql"));
Reader productTableSql = new InputStreamReader(
DatabaseConnectorTests.class.getResourceAsStream(
"/migrations/V3__create_products_table.sql"));
this.dc = DatabaseConnector.getConnection();
RunScript.execute(dc, storeTableSql);
RunScript.execute(dc, regionTableSql);
RunScript.execute(dc, productTableSql);
Я получаю следующую ошибку:
org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "CREATE TABLE PRODUCTS (
ID INTEGER AUTO_INCREMENT PRIMARY KEY,
STORE_ID INTEGER NOT NULL,
NAME VARCHAR(255) NOT NULL,
REGION_ID INTEGER NOT NULL,
CREATED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UPDATED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
DELETED_AT TIMESTAMP,
UNIQUE(STORE_ID, NAME),
FOREIGN KEY STORE_FK[*](STORE_ID) REFERENCES STORES(ID),
FOREIGN KEY REGION_FK(REGION_ID) REFERENCES REGIONS(ID)
) "; expected "("; SQL statement:
CREATE TABLE products (
id integer AUTO_INCREMENT PRIMARY KEY,
store_id integer NOT NULL,
name varchar(255) NOT NULL,
region_id integer NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at timestamp,
UNIQUE(store_id, name),
FOREIGN KEY store_fk(store_id) REFERENCES stores(id),
FOREIGN KEY region_fk(region_id) REFERENCES regions(id)
) [42001-196]
Этот код работает в MySQL, и я запускаю H2 в режиме совместимости MySQL с помощью следующей строки подключения: jdbc:h2:file:~/database;MODE=MySQL
. Я не уверен, что еще я могу сделать здесь. Эта ошибка кажется мне очень странной, поскольку я понятия не имею, почему она думает, что мне нужен ДРУГОЙ (
.
Кто-нибудь знает, как это исправить? Или есть лучшее предложение о том, как засеять мою тестовую базу данных? Я не могу использовать спящий режим для этой задачи из-за ограничения на систему, на которой я запущен, поэтому я вынужден много выполнять вручную.
Спасибо!
Из этого поста, но с небольшим количеством объяснений.
Внешние ограничения ключа во H2 не допускают именованных ограничений по любой причине. Решение этой проблемы - просто удалить имя:
CREATE TABLE products (
id integer AUTO_INCREMENT PRIMARY KEY,
store_id integer NOT NULL,
name varchar(255) NOT NULL,
region_id integer NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at timestamp,
UNIQUE(store_id, name),
FOREIGN KEY (store_id) REFERENCES stores(id),
FOREIGN KEY (region_id) REFERENCES regions(id)
);
Сообщение об ошибке настолько непонятно и вводит в заблуждение. Надеюсь, это помогает кому-то.