在获取输出参数之前,Jaybird CallableStatement不会执行

时间:2013-08-04 19:26:58

标签: java stored-procedures jdbc callable-statement jaybird

我有这个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_coordinatesFirebird存储过程:

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表中的数据被更新。

1 个答案:

答案 0 :(得分:0)

问题是您在存储过程中使用SUSPEND。关键字SUSPEND适用于可选存储过程(生成多行数据的存储过程)。由于您的存储过程只生成一行,因此SUSPEND是不必要的(原因)。

对于可选择的程序,Jaybird会将您的execute procedure rm_set_coordinates(?,?,?)转换为SELECT * FROM rm_set_coordinates(?,?,?)。我不是百分之百确定Firebird存储过程的实现细节,但看起来像包含SUSPEND的块只能在实际获取行时执行,或者所有更改都可以执行前一个SUSPEND在语句关闭或重用之前未提取行时还原。

但最终结果是:没有提取任何行,也没有更改。当执行可选择的存储过程(即:它包含SUSPEND)时,Jaybird以与“正常”可执行存储过程不同的方式检索结果。

已知可执行存储过程只有一行(或没有行)结果,因此在执行时会立即检索这些值,并且可以使用getXXX()方法检索结果。对于可选择的存储过程,结果像普通ResultSet一样被检索。通常,对于可选择的存储过程,您应该使用executeQuery()并处理返回的ResultSet。由于实现工艺和与旧版Firebird的兼容性(无法区分可选和可执行的过程),因此可以使用以下方法检索ResultSet的第一行(或当前行)的值。 getXXX()的{​​{1}}方法。

TL; DR :删除CallableStatement

披露:我是Jaybird的开发者之一