Spring JDBC не может обработать оператор DECLARE при запуске сценария SQL

У меня есть приложение 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
}

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


Есть идеи?

10000