命名参数未在jdbc中正确传递

时间:2019-07-04 02:52:52

标签: oracle jdbc java-7

我正在使用JDBC CallableStatement调用带有命名参数的过程。

程序:

create or replace PROCEDURE VIST_COMP(I_STUDY IN VARCHAR2, I_STARTDATE IN VARCHAR2, I_ENDDATE IN VARCHAR2, I_EMPLOYEE IN VARCHAR2, I_EMPLOYEE_OPTIONAL IN NUMBER, I_SPONSOR IN VARCHAR2, I_SPONSOR_OPTIONAL IN NUMBER, p_rc OUT SYS_REFCURSOR)
AS
o_cursor SYS_REFCURSOR;
sqlqry clob;
BEGIN
  //procedure code 
END VIST_COMP;

Java代码:

String runSP = "call VIST_COMP(:protocols,:alertStartDate,:alertEndDate,:employee,:employeeOptional,:sponsor,:sponsorOptional, :out_cursor)";         
try (Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:localhost:389/oracle", "username", "password");
CallableStatement callableStatement = conn.prepareCall(runSP)) {
   callableStatement.setString("protocols","12345");
   callableStatement.setString("alertStartDate", "03-Apr-2019");
   callableStatement.setString("alertEndDate", "03-Jun-2019");
   callableStatement.setString("employee",null);
   callableStatement.setInt("employeeOptional",1);
   callableStatement.setString("sponsor", "abc");
   callableStatement.setInt("sponsorOptional",0);

   callableStatement.registerOutParameter("out_cursor", OracleTypes.CURSOR);

   // run it
   callableStatement.execute();
   ResultSet rset = (ResultSet)   callableStatement.getObject("out_cursor");

   while(rset.next()) {
     System.out.println(rset.getString("LABEL_VALUE"));
   }
}catch(Exception e) {
   e.printStackTrace();
}

以上代码运行良好,我也收到了ResultSet。但是问题是,如果我更改设置参数的顺序,它将不起作用。例如,如果我将sponsor设置为高于日期,例如下面给出错误提示。

callableStatement.setString("protocols","12345");
callableStatement.setString("alertStartDate", "03-Apr-2019");
callableStatement.setString("sponsor", "abc");
callableStatement.setString("alertEndDate", "03-Jun-2019");
callableStatement.setString("employee",null);
callableStatement.setInt("employeeOptional",1);
callableStatement.setInt("sponsorOptional",0);

数据库错误是

  

ORA-01858:发现一个非数字字符,其中数字为   预期

     

ORA-06512:位于“ VIST_COMP”的第266行

使用构建路径Java 1.7(已安装JDK 1.8),Oracle 12c,Ojdbc6.jar。

1 个答案:

答案 0 :(得分:0)

如果要使用命名参数来调用Oracle存储过程,可以考虑使用morejdbc。您的通话将如下所示:


import static org.morejdbc.NamedJdbcCall.call;
import org.morejdbc.*;
import org.springframework.jdbc.core.RowMapper;

// I do not know the structure of returned ref_cursor, so let it be a single column of varchar
RowMapper<String> mapper = (rs, rowNum) -> rs.getString("value");
Out<List<String>> resultOut = Out.of(OracleSqlTypes.cursor(mapper));
jdbcTemplate.execute(call("VIST_COMP")
    .in("protocols", "12345") // note: argument name is Oracle PL/SQL argument name
    .in("alert_start_date", "03-Apr-2019")
    .in("alert_end_date", "03-Jun-2019")
    .in("employee", null)
    .in("employeeOptional", 1)
    .in("sponsor", "abc")
    .in("sponsorOptional", 0),
    .out("out_cursor", resultOut));

System.out.println("Result is " + resultOut.get());

它需要Java 1.8和spring,但是如果您的项目有另一个堆栈,则可以方便地至少改写辅助类。