Как передать функцию в качестве значения аргумента в JDBC подготовлено состояние, CallableStatement или Spring-JDBC StoredProcedure? - PullRequest
1 голос
/ 22 марта 2012

Я использую Spring Jdbc для выполнения некоторых хранимых процедур вызовов с использованием StoredProcedure класса.

Некоторые процедуры принимают дату в качестве входного параметра.
(я не могу изменить процедуры: они находятся вне моего проекта)

В моей бизнес-логике у меня есть несколько правил о дате:
в некоторых случаях для того же процесса мне может потребоваться указать произвольную дату ИЛИ текущую системную дату базы данных (ключевое слово ORACLE sysdate)

Как мне предоставить такой параметр при вызове процедуры?
Если я передаю «sysdate», spring и jdbc разрешают это как тип VARCHAR, и вызов не выполняется.

Я не хочу сначала вызывать базу данных для получения 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 Ответ

1 голос
/ 22 марта 2012

Я не думаю, что StoredProcedure (или иерархия RdbmsOperation в целом) помогут вам здесь.Их логика вокруг генерации строки вызова не написана таким образом, чтобы разрешать расширение и настройку.

Мое предложение состояло бы в том, чтобы отказаться от StoredProcedure и использовать JdbcTemplate напрямую.Это больше похоже на ошибку, но вы получаете полный контроль над строкой вызова.Затем, когда вам нужно вызвать вашу процедуру с помощью sysdate, вы можете просто: добавить ее в строку вызова, например,

{call TEST_PROC(?, ?, sysdate)}

. Вам нужно будет динамически решить, использовать ли строку вызова сsysdate, или один без, и решите, какие параметры добавить соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...