2

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

4

1 回答 1

0

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

对于可选择的程序,Jaybird 将您转换execute procedure rm_set_coordinates(?,?,?)SELECT * FROM rm_set_coordinates(?,?,?). 我不是 100% 确定 Firebird 存储过程的实现细节,但看起来包含 a 的块SUSPEND要么仅在实际获取行时执行,要么在之前SUSPEND未获取行时恢复之前的所有更改语句被关闭或重用。

然而,最终结果是:没有获取行,没有更改。执行可选存储过程(即:它包含一个SUSPEND)时,Jaybird 检索结果的方式与它是“正常”可执行存储过程时不同。

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

TL;DR:删除SUSPEND.

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

于 2013-08-05T07:40:26.950 回答