У меня есть приложение Spring CRUD, с базой данных Oracle SQL.
У меня есть несколько интеграционных тестов, и я использую аннотацию @Sql
для запуска файлов .sql, которые перед выполнением теста переводят базу данных в нужное состояние. До сих пор у меня не было проблем ни с одним из моих скриптов .sql, хотя все они были очень простыми операторами INSERT и DROP.
Сейчас я пытаюсь настроить сценарий, в котором база данных содержит тысячи записей в конкретной таблице. Меня не беспокоит содержание, только количество записей.
Чтобы повторить этот сценарий, я написал следующий сценарий SQL:
DECLARE
id integer := 1;
BEGIN
WHILE id <= 3000
LOOP
INSERT INTO USER (ID, FIRST_NAME, LAST_NAME, AGE)
VALUES (id, 'John', 'Smith', 32);
id := id + 1;
END LOOP;
END;
Я запустил этот скрипт, используя IntelliJ, и он работает как положено.
Однако, когда я помещаю скрипт в аннотацию @Sql, я сталкиваюсь со следующей ошибкой:
org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of class path resource [sql/setUp.sql]: DECLARE id integer := 1; nested exception is java.sql.SQLException: ORA-06550: line 1, column 23:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
* & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
Я в растерянности относительно решения; Я сталкивался с похожими проблемами, когда решением была просто пропущенная точка с запятой, но здесь это не так. Еще более загадочным является то, что я попытался запустить следующий скрипт с помощью аннотации @Sql:
BEGIN
INSERT INTO USER (ID, FIRST_NAME, LAST_NAME, AGE)
VALUES (1, 'John', 'Smith', 32);
END;
Это привело к следующей ошибке, которая имеет еще меньше смысла:
org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of class path resource [sql/test.sql]: BEGIN INSERT INTO USER (ID, FIRST_NAME, LAST_NAME, AGE) VALUES (1, 'John', 'Smith', 32); nested exception is java.sql.SQLException: ORA-06550: line 1, column 87:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
;
Самое интересное отметить, что удаление операторов BEGIN и END (оставляя только оператор INSERT INTO) работает.
Так что Spring JDBC просто не поддерживает блоки BEGIN / END? Есть ли ограничения аннотации @Sql перед тестом, о которых я не знаю? Или я что-то упустил до боли очевидный?
Всего 1 ответ
Спасибо @MarkRotteveel за его предложение, я нашел решение этой проблемы.
JDBC действительно выполнял каждую строку скрипта, как если бы это был отдельный оператор, который несовместим с блоками операторов. Это потому, что separator
установлен в ;
символ по умолчанию, заставляющий JDBC обрабатывать каждый блок кода, оканчивающийся на ;
как будто это был отдельный сценарий. Я установил этот разделитель на символ EOF, что заставило JDBC обрабатывать весь файл как один скрипт.
Мой оригинальный тестовый код выглядел примерно так:
@Sql(scripts = {"sql/cleanup.sql", "sql/setUp.sql"})
public void testWithThousandsOfRecords() {
// do tests
}
Мой тестовый код теперь выглядит так:
@Sql(scripts = "sql/cleanup.sql")
@Sql(scripts = "sql/setUp.sql", config = @SqlConfig(separator = ScriptUtils.EOF_STATEMENT_SEPARATOR))
public void testWithThousandsOfRecords() {
// do tests
}
Обратите внимание, что мне пришлось разделить сценарии очистки и настройки, так как изменение разделителя может нарушить некоторые сценарии, которые работали раньше.