JDBC - 从Oracle Procedure中检索布尔输出

时间:2016-04-12 05:26:40

标签: stored-procedures boolean spring-jdbc jdbctemplate

我需要使用一个带有VARCHAR2和OUT参数的IN参数作为BOOLEAN数据类型来调用Oracle过程。

以下是使用SimpleJdbcCall

的代码
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(getTemplate()) 
            .withCatalogName("package_name")
            .withProcedureName("proc_name")
            .withoutProcedureColumnMetaDataAccess()
            .declareParameters(
                new SqlParameter ("userName", Types.VARCHAR), 
                new SqlOutParameter("status", Types.BOOLEAN)
            );                  
Map<String, Object> inParams = new HashMap<String, Object>();
inParams .put("userName",  userInput);
Map<String, Object> outputValue= jdbcCall.execute(inParams);
  

异常:CallableStatementCallback;未分类的SQLException for   SQL [{call PACKAGE_NAME.PROC_NAME(?,?)}]; SQL状态[99999];   错误代码[17004];列类型无效:16;嵌套异常是   java.sql.SQLException:列类型无效:16

进行研究后发现“ JDBC驱动程序不支持将布尔参数传递给PL / SQL存储过程

建议使用第二个PL / SQL过程包装PL / SQL过程。主要问题是我在数据库中限制写入访问,因为它是客户端数据。请帮我解决这个问题。

我提到的一些链接

  1. https://docs.oracle.com/cd/F49540_01/DOC/java.815/a64685/tips3.htm
  2. https://community.oracle.com/thread/2139408?tstart=0
  3. https://community.oracle.com/thread/887712?tstart=0
  4. https://community.oracle.com/thread/975159?tstart=0
  5. Stored Function - Sending/Receiving Boolean - BD
  6. http://docs.oracle.com/cd/B28359_01/java.111/b31224/apxtblsh.htm#i1005380

2 个答案:

答案 0 :(得分:3)

我通过编写一个包装程序来处理实际过程的结果并将结果作为varchar数据类型发回来修复了这个问题。 如果您有任何人认为这是错误的方法,或者您有任何简单的方法来解决这个问题,请分享您的意见。

以下是程序:

DECLARE 
userName VARCHAR2(13);  
status BOOLEAN;  
result VARCHAR2(13); 

BEGIN 
userName := ?; 
status := NULL; 
package_name.proc_name ( userName, status); 
BEGIN 
IF status THEN result := 'Yes'; 
ELSIF NOT status THEN result := 'No'; 
ELSE result := 'NULL'; 
END IF; 
END; 
COMMIT; 
? := result;
END ;

我还使用CallableStatement来处理它,而不是simpleJdbcCall。请参阅以下内容:

try{
    String wrapperProc= "DECLARE userName VARCHAR2(13);  status  BOOLEAN;  result VARCHAR2(13); BEGIN userName := ?; status := NULL; "+
        "package_name.proc_name ( userName, status ); BEGIN IF status THEN result := 'Yes'; ELSIF NOT status THEN " + 
            "result := 'No'; ELSE result := 'NULL'; END IF; END; COMMIT; ? := result;END ;";
    CallableStatement proc_stmt= null;
    proc_stmt = getTemplate().getDataSource().getConnection().prepareCall(wrapperProc);
    proc_stmt.setString(1, "userName");   
    proc_stmt.registerOutParameter(2, Types.VARCHAR);
    proc_stmt.execute();
    System.out.println("Final Result : "+proc_stmt.getString(2));
} catch(SQLException e){
    System.out.println("SQL Exception : "+e.getMessage());
    e.printStackTrace();
} catch (Exception e) {
    System.out.println("Exception : "+e.getMessage());
    e.printStackTrace();
}

~~素里亚

答案 1 :(得分:3)

来自官方的Oracle JDBC documentation

  

Oracle JDBC驱动程序支持调用是不可行的   PL / SQL RECORD,BOOLEAN或表的参数或返回值   非标量元素类型。 [...]作为PL / SQL RECORD的解决方法,   BOOLEAN或非标量表类型创建容器过程   将数据作为JDBC支持的类型处理。例如,包装一个   使用PL / SQL布尔值的存储过程,创建一个存储过程   从JDBC获取一个字符或数字并将其传递给   原始过程为BOOLEAN,或者对于输出参数,接受a   来自原始过程的BOOLEAN参数并将其作为CHAR传递   或NUMBER到JDBC。同样,要包装使用的存储过程   PL / SQL记录,创建一个处理其中记录的存储过程   单个组件,例如CHAR和NUMBER,或结构化的组件   对象类型。

这正是您在答案中所做的,但我想添加文档作为参考。