Firebird DB上的SimpleJdbcCall NullPointerException

时间:2014-04-23 07:58:14

标签: sql spring stored-procedures jdbc firebird

我在Firebird上调用存储过程时遇到问题。我的过程有一个参数(UID)并返回一个值ID。

...
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
// sp declaration
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
      .withProcedureName("SP_NEWRECORD").declareParameters(
       new SqlParameter("UID", Types.INTEGER),
       new SqlOutParameter("NEWID", Types.INTEGER));
Map<String, Object> in = new HashMap<String, Object>();
in.put("UID", uid);
in.put("NEWID", 0);

try {
Map<String, Object> out = jdbcCall.execute(in); //here throws Exception
    last_inserted = Integer.parseInt(String.valueOf(out.get("NEWID")));
} catch (Exception ex) {
    ex.printStackTrace();
} finally {
    System.out.println("createRecord result id=" + last_inserted);
}
// return id of inserted record
return last_inserted;

Catalina out

java.lang.NullPointerException
at org.firebirdsql.jdbc.AbstractResultSet.getRow(AbstractResultSet.java:1307)
at org.firebirdsql.jdbc.AbstractCallableStatement.assertHasData(AbstractCallableStatement.java:998)
at org.firebirdsql.jdbc.AbstractCallableStatement.getObject(AbstractCallableStatement.java:773)
at com.mchange.v2.c3p0.impl.NewProxyCallableStatement.getObject(NewProxyCallableStatement.java:675)
at org.springframework.jdbc.core.JdbcTemplate.extractOutputParameters(JdbcTemplate.java:1168)
SP的代码非常简单,在表中创建新记录并返回插入记录的ID

ALTER PROCEDURE SP_NEWRECORD (UID integer)
RETURNS (NEWID integer)
AS
declare variable ID integer;
begin
  ID=GEN_ID(gen_myrecords_id,1);
  insert into myrecords (id,uid)
  values (:id,:uid);
  newid=ID;
end

1 个答案:

答案 0 :(得分:1)

最终的问题是,目前Jaybird没有明确区分OUT参数(Firebird技术上没有),可执行程序的(单行)返回值和(多行)结果一组可选择的存储过程。您遇到的问题(至少部分)与JDBC-229相关(以及对Jaybird 3.0计划的CallableStatement实施的一般性审核)。

这会导致支持单行的结果集被读取两次,一次作为ResultSet,一次通过CallableStatement上的getter,但是当支持结果集已关闭时,这会在检索到NullPointerException参数时导致OUT

有两种可能的解决方法:

  1. 禁用JdbcTemplate上的结果处理:

    JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
    jdbcTemplate.setSkipResultsProcessing(true);
    
  2. 不要声明OUT参数,并处理out地图中返回的结果集(其中包含带有List的{​​{1}}结果集):

    Map
  3. 请注意,从last_inserted = (int) ((List<Map>) out.get("#result-set-1")).get(0).get("NEWID"); Object的强制转换假设为Java 7或更高版本。

    我已将此特定问题报告为JDBC-350,我将尝试在下一个Jaybird版本(2.2.6)中修复此问题。