Spring JDB C не может обработать оператор DECLARE при запуске SQL Script - PullRequest
0 голосов
/ 12 февраля 2020

У меня есть приложение 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 JDB C просто не поддерживает блоки BEGIN / END? Существуют ли ограничения для аннотации перед тестом @ Sql, о которых я не знаю? Или я что-то упустил до боли очевидный?

1 Ответ

1 голос
/ 12 февраля 2020

Спасибо @MarkRotteveel за его предложение, я нашел решение этой проблемы.

JDB C действительно выполнял каждую строку сценария, как если бы это был отдельный оператор, что несовместимо с блоки выписок. Это связано с тем, что по умолчанию separator установлен на символ ;, в результате чего JDB C обрабатывает каждый блок кода, заканчивающийся ;, как если бы это был отдельный скрипт. Я установил этот разделитель на символ EOF, что заставило JDB C рассматривать весь файл как один скрипт.

Мой исходный тестовый код выглядел примерно так:

@Sql(scripts = {"sql/cleanup.sql", "sql/setUp.sql"})
public void testWithThousandsOfRecords() {
  // do tests
}

My тестовый код теперь выглядит следующим образом:

@Sql(scripts = "sql/cleanup.sql")
@Sql(scripts = "sql/setUp.sql", config = @SqlConfig(separator = ScriptUtils.EOF_STATEMENT_SEPARATOR))
public void testWithThousandsOfRecords() {
  // do tests
}

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

...