2012-03-22 4 views
1

Я использую Spring JDBC для выполнения некоторых хранимых процедур вызовов с использованием StoredProcedure класса.как передать функцию как значение аргумента в jdbc prepareStatement, CallableStatement или Spring-jdbc StoredProcedure?

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

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

Как мне предоставить этот параметр при вызове proc?
Если я передаю «sysdate», пружина и 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

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

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

{call TEST_PROC(?, ?, sysdate)} 

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

+0

К сожалению, это выглядит печально. Я потратил некоторое время на попытку создать расширенный класс SimpleJdbcCall, который изменит '?' к желаемой функции expr. Но теперь CallableStatementCreatorFactory сбой при подготовке карты параметров для выполнения db ... С еще большим количеством времени я смогу исправить это ... но это будет много беспорядка ... Я пытался конвертировать мой босс и команда, чтобы использовать spring-jdbc, чтобы избежать нашего сырого суффома. Не уверен, что это будет играть в пользу Весны ... – Guillaume