Jaybird CallableStatement не выполняется до получения выходного параметра

У меня есть этот код Java:

Connection conn = connectionProvider.getConnection();
statement = conn.prepareCall("execute procedure rm_set_coordinates(?,?,?)");
statement.setInt(1, userId);
statement.setString(2, String.valueOf(location.getLatitude()));
statement.setString(3, String.valueOf(location.getLongitude()));
statement.execute();

Где rm_set_coordinates — это Firebird хранимая процедура:

create or alter procedure RM_SET_COORDINATES (
    PCAR_LOGIN integer,
    PLAT varchar(20) = 0,
    PLNG varchar(20) = 0)
returns (
    ORESULT integer,
    ORESULT_MSG varchar(500))
as
begin
     update ref_car rc  set rc.rm_last_connect_time='now',rc.rm_lat=:plat,rc.rm_lng=:PLNG  where rc.id=:pcar_login;
     oresult=1;
     oresult_msg='';
  suspend;
end

Когда я выполняю этот код, данные в таблице ref_car не меняются. Но если я добавлю эту строку в приведенный выше код:

statement.getInt(1);

который возвращает значение выходного параметра oresult, тогда все в порядке, данные в таблице ref_car обновляются.


person mixel    schedule 04.08.2013    source источник


Ответы (1)


Проблема в том, что вы используете SUSPEND в хранимой процедуре. Ключевое слово SUSPEND предназначено для выбираемых хранимых процедур (хранимые процедуры, которые создают несколько строк данных). Поскольку ваша хранимая процедура создает только одну строку, SUSPEND не нужен (и причина).

Для выбираемой процедуры Jaybird преобразует ваш execute procedure rm_set_coordinates(?,?,?) в SELECT * FROM rm_set_coordinates(?,?,?). Я не уверен на 100% в деталях реализации хранимых процедур Firebird, но похоже, что блок, содержащий SUSPEND, либо выполняется только тогда, когда строка фактически извлекается, либо все изменения до предыдущего SUSPEND отменяются, когда строка не извлекается. перед закрытием или повторным использованием оператора.

Конечный результат, однако, таков: ни строк, ни изменений. При выполнении выбираемой хранимой процедуры (т. е. содержащей SUSPEND) Jaybird извлекает результаты другим способом, чем при выполнении «обычной» исполняемой хранимой процедуры.

Известно, что исполняемая хранимая процедура имеет только одну строку (или ни одной строки) результатов, поэтому эти значения извлекаются сразу при выполнении, а результат можно получить с помощью методов getXXX(). Для выбираемой хранимой процедуры результаты извлекаются как обычно ResultSet. Обычно для выбираемой хранимой процедуры следует использовать executeQuery() и обрабатывать возвращенное ResultSet. Из-за артефакта реализации и совместимости со старыми версиями Firebird (где не было возможности различать выбираемые и исполняемые процедуры) можно получить значения первой (или текущей) строки ResultSet с помощью getXXX() методов getXXX() CallableStatement тоже.

TL;DR: удалите SUSPEND.

Раскрытие информации: я являюсь одним из разработчиков Jaybird.

person Mark Rotteveel    schedule 05.08.2013