5

INSybase JDBC ドライバーがとOUTパラメーターが混在するストアド プロシージャをどのように処理するかについて、私は気が狂っています。この単純なストアド プロシージャを確認してください。

CREATE OR REPLACE PROCEDURE p (IN i1 INT, OUT o1 INT, IN i2 INT, OUT o2 INT)
BEGIN
    set o1 = i1;
    set o2 = i2;
END

そして、JDBCでそれを呼び出す方法は次のとおりです。

CallableStatement c = connection.prepareCall("{ call dba.p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(2));
System.out.println(c.getObject(4));

しかし、これは

1
null

どうしたの??それは JDBC ドライバーの本当に厄介なバグですか、それとも完全に何かが欠けているのでしょうか? 試行錯誤の結果、次のように動作することがわかりました。

c.setInt(1, 1);
c.setInt(2, 2);
c.registerOutParameter(3, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(3));
System.out.println(c.getObject(4));

今、結果は

1
2

JDBC ドライバーはひそかに順序INOUTパラメーターを変更しますか??

SQL Anywhere 12 と jconn3.jar を使用しています

4

3 に答える 3

7

ドライバーのバグのようです。

バギードライバーは、パラメーターが順番に(つまり、1、2、3、4)渡される/登録されることを期待していると思います。registerOut(2)を実行すると、ステートメントは明らかにset(3)を実行したことを忘れます:-)

または、可能性がありますが、すべてのOUTはすべてのINの後に実行する必要があります。繰り返しになりますが、これはドライバーのバグです。

アップデート

待って、2番目のバリアントの手順を変更しなかったのですか?その結果は意味がありませ。あなたが言ったように、ドライバーが並べ替えをしない限り。控えめに言っても、これは珍しいことです。

更新2

ドライバーを逆コンパイルしました。それはパラメータの周りでいくつかのかなり面白いゲームをします、そしてこのすべてのジョグリングで私はそれらがそこにバグのかなりの可能性を持っていると感じます、しかし今のところ私はそれをはっきりと見ていません。

私が気付いた唯一の面白いことは、位置nのパラメーターが出ていない場合、ドライバーは値が見つかるまでパラメーターを前方にスキャンすることです。値が見つからない場合は、次の行に移動します。

  s.registerOutParameter(5,Types.INT);
  ...
  // no out value at position 4, it will go to 5 and get the value
  rs.getInteger(4);

更新3

例1の4つのパラメーターすべての出力を確認することは、興味深いかもしれません。

CallableStatement c = connection.prepareCall("{ call dba.p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(1));
System.out.println(c.getObject(2));
System.out.println(c.getObject(3));
System.out.println(c.getObject(4));
于 2011-05-10T04:37:37.697 に答える
4

これを Oracle 9.2 で試したところ、期待どおりに動作しました。この問題は、JDBC 自体ではなく、JDBC ドライバーに関連していると思います。

    public static void main(String[] args) throws Exception {

    Connection connection = getConnection();

    CallableStatement c = connection.prepareCall("{ call p(?, ?, ?, ?) }");
    c.setInt(1, 1);
    c.setInt(3, 2);
    c.registerOutParameter(2, Types.INTEGER);
    c.registerOutParameter(4, Types.INTEGER);
    c.execute();
    System.out.println(c.getObject(2));
    System.out.println(c.getObject(4));

}

出力:

Connected to database
1
2
于 2011-05-09T11:25:24.097 に答える
1
Below sybase stored procedure works for me
public String IDGEN(String tableName,  Connection con , LOG _log)
    { 
        String strReturnValue = "-1"; 
        try
        {
             CallableStatement cs = con.prepareCall("{call usp_NEWPK_string_v6(?,?)}");
             cs.registerOutParameter(2,java.sql.Types.NUMERIC);
             cs.setString(1,tableName);
             cs.setInt(2,0);
             cs.execute();
             strReturnValue = cs.getLong(2) + "";

        } catch (Exception ex) {
            _log.logInstance(" ERROR: [IDGEN] " + ex.getMessage()); 
        }
        return strReturnValue;
    } 
// abobjects.com

create proc usp_NEWPK_string_v6 (@tablename  varchar(32) , @ID  numeric output
          )
as
declare @newValue     numeric
declare @oldValue  numeric
select @oldValue=IDGEN_ID from DB_IDGEN where IDGEN_TableName = @tablename
select @newValue=@oldValue + 1 from DB
 _IDGEN where IDGEN_TableName = @tablename
update DB_IDGEN set IDGEN_ID = @newValue where IDGEN_TableName = @tablename
select @ID  = @oldValue
return
于 2014-01-13T18:35:08.087 に答える