【问题标题】:Invoking procedure defaults without binding values to parameters in Jdbc调用过程默认值而不将值绑定到 Jdbc 中的参数
【发布时间】:2014-12-11 22:46:54
【问题描述】:

我正在尝试调用一个PL/SQL 过程,该过程为其某些参数定义了默认值。我在JDBC 中使用CallableStatement 来执行此操作。

此过程有大量参数定义了默认值。我不想在 Java 代码中显式设置默认值。这样做会使代码的维护变得更加困难。如果 PL/SQL 代码发生变化,Java 代码也必须进行相同的更改。

是否可以在 JDBC 中完成此操作?例如,只需将值绑定到您感兴趣的参数,而忽略其余的。

我在以下示例过程中尝试过:

  -- PURPOSE: Takes a parameter which has defaults set. Returns the value of the same parameter
  -- Example of: FUNCTION that takes a parameter with DEFAULT values  
  FUNCTION handle_defaults(empId IN NUMBER DEFAULT 20 , empCity IN VARCHAR2) RETURN NUMBER IS
  BEGIN
    RETURN empId;
  EXCEPTION
    WHEN others THEN
    dbms_output.put_line('Error!');
  END handle_defaults;

以下是代码的相关部分(注意:为了可读性,已剥离 try catch 块、清理数据库资源等)

         // Create a database connection
         conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PWD);

         // Create a query string
         String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( ? , ? ) }";

         // Create a Callable Statements
         callStmt = conn.prepareCall(queryStr);

         // Bind values to the IN parameter
         callStmt.setString(3, "Mumbai");

         // Register OUT parameter 
         callStmt.registerOutParameter(1, java.sql.Types.NUMERIC);

         // Execute the Callable Statement
         callStmt.execute();

         // Retrieve the value of the OUT parameter
         parameterValue = callStmt.getInt(1);

         System.out.println("Value returned : " + parameterValue);

我收到以下错误:

Exception occured in the database
java.sql.SQLException: Missing IN or OUT parameter at index:: 2
Database error code: 17041

作为绝望的尝试,我还尝试为这些参数传递 Null。只包含以下行:

callStmt.setNull(2, java.sql.Types.NUMERIC);

我得到以下结果:

Value returned : 0

这是有道理的 bcoz setNull 将 SQL Null 提供给参数。

我正在使用Oracle 11gOracle 12c Jdbc Driver Version 12.1.0.2

【问题讨论】:

    标签: java jdbc data-binding parameters default


    【解决方案1】:

    我认为这个问题没有简单的答案,这不是因为 JDBC,而是因为 Oracle。

    简单地说,我知道调用过程并使用参数默认值的唯一方法是在调用过程时不指定参数。

    如果你正在写作

         String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( ? , ? ) }";
    

    你总是指定两个参数,所以你永远不能为其中一个使用默认值。如果您只想指定其中一个并为另一个使用默认值,请编写:

         String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( empCity => ? ) }";
    

    在这种情况下,您需要在调用中指定参数名称,因为第一个参数是可选的。如果第二个参数是可选的,则可以删除参数名称。

    不幸的是,对于有很多参数的实际过程来说,这变得相当复杂。我会做的是:

    • 使用 StringBuilder 构建过程调用字符串。
    • 遍历参数,为每个有值的参数添加paramName => ? 部分。确保各部分用逗号分隔。
    • 使用 StringBuilder 的输出准备 CallableStatement。
    • 再次运行参数,调用各种setString/setInt/setDate/等。 CallableStatement 上的方法,为您为其赋值的每个参数。

    【讨论】:

    • 我希望有更简单、更优雅的方式来做到这一点。不过好像没有。感谢字符串生成器的想法!!
    猜你喜欢
    • 1970-01-01
    • 2012-08-06
    • 1970-01-01
    • 2015-09-28
    • 2011-03-05
    • 2010-10-01
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    相关资源
    最近更新 更多