如何在jdbc preparedStatement,CallableStatement或Spring-jdbc StoredProcedure中将函数作为参数值传递?

时间:2012-03-22 13:12:39

标签: stored-procedures jdbc spring-jdbc

我正在使用 Spring Jdbc 使用 StoredProcedure 类执行一些存储过程调用。

有些程序将日期作为输入参数 (我无法更改程序:它们不在我的项目中)

在我的业务逻辑中,我有一些关于约会的规则:
在某些情况下,对于相同的proc,我可以提供任意日期或数据库的当前系统日期(ORACLE sysdate关键字)

调用proc时如何提供这种参数?
如果我传递“sysdate”,则spring和jdbc将其解析为VARCHAR类型,并且调用失败。

我不想先调用db来检索sysdate,就像我在一些文档中看到的那样。

更一般地说,当使用'?'来使用所有JDBC时,我应该如何做到这一点?作为sql查询参数的占位符? 我花了一些时间试图找到一种方法来做到这一点,但我找不到答案。

测试DDL:

CREATE TABLE "AAATEST" ("A_TEXT" VARCHAR2(20 BYTE), "A_DATE" DATE, "A_NUMBER" NUMBER) ;

create or replace PROCEDURE TEST_PROC ( someText in VARCHAR2, someNumber in NUMERIC, someDate in date) IS
BEGIN
    insert into AAATEST(a_text, a_number, a_date) values (someText, someNumber, someDate);
END;

Java中的测试类:

public class Test {
  public static class MyStoredProc extends StoredProcedure {
    protected MyStoredProc(DataSource ds) {
      super(ds, "test_proc");
      declareParameter(new SqlParameter("someText", Types.VARCHAR));
      declareParameter(new SqlParameter("someNumber", Types.NUMERIC));
      declareParameter(new SqlParameter("someDate", Types.DATE));
    }
  }

  public static void main(String[] args) {
    DataSource ds = new SingleConnectionDataSource("driver", "url", "username","password",false);
    MyStoredProc myStoredProc = new MyStoredProc(ds);

    //this one is ok
    myStoredProc.execute(new HashMap(){{
      put("someText", "hello world");
      put("someNumber", 3.14);
      put("someDate", new Date());
    }});

    //this one fails with 'Exception in thread "main" java.lang.IllegalArgumentException at java.sql.Date.valueOf(Date.java:140)'
    myStoredProc.execute(new HashMap(){{
      put("someText", "abc");
      put("someNumber", 123);
      put("someDate", "sysdate");
    }});            
  }
}

1 个答案:

答案 0 :(得分:1)

我认为StoredProcedure(或一般的RdbmsOperation层次结构)不会在这里帮助你。它们围绕调用字符串生成的逻辑不是以允许扩展和自定义的方式编写的。

我的建议是放弃StoredProcedure并直接使用JdbcTemplate。它更像是一个faff,但你可以完全控制调用字符串。然后,当您需要使用sysdate调用您的过程时,您可以:将其添加到调用字符串中,例如

{call TEST_PROC(?, ?, sysdate)}

您需要动态决定使用sysdate或不使用的调用字符串,并决定相应添加哪些参数。