【问题标题】:Jaybird CallableStatement not executed until getting output parameter在获取输出参数之前,Jaybird CallableStatement 不会执行
【发布时间】:2013-08-05 11:39:27
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    TL;DR:删除SUSPEND

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

    【讨论】:

      猜你喜欢
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-07
      • 2022-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多