2016-07-28 3 views
1

Я создал пользовательский тип в оракуле, как показано ниже.Отправка пустого списка в хранимую процедуру

create or replace TYPE "ABC_OBJECT" AS OBJECT (
    ticket_no VARCHAR2(50), 
); 

create or replace TYPE "ABC_OBJECT_LIST" IS TABLE OF ABC_OBJECT; 

ABC_OBJECT_LIST Тип используется как тип данных для поля ввода в хранимой процедуре. Я вызываю хранимую процедуру из своего java-кода. Я написал специальный TypeHandler для обработки ввода типа списка и перехода к хранимой процедуре. Все работает, и я могу отправить свои значения в хранимую процедуру и получить их успешно, используя приведенный ниже код в обработчике.

@Override 
    public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType arg3) throws SQLException { 
     List<Object> object = (List<Object>)parameter; 
     structDescriptor = getStructureDescriptor(con, PASSENGER_DETAILS_JDBC_OBJECT); 
     arrayDescriptor = getJDBCArrayDescriptor(con, PASSENGER_DETAILS_JDBC_OBJECT_LIST); 

     STRUCT[] structs = new STRUCT[objects.size()]; 
     for (int index = 0; index < objects.size(); index++) { 
     structs[index] = getJDBCDataObject(structDescriptor, con, objects.get(index)); 
     } 

     ARRAY oracleArray = getJDBCArrayObject(arrayDescriptor, con, structs); 
     ps.setArray(i, oracleArray); 
    } 

    private STRUCT getJDBCDataObject(final StructDescriptor structDescriptor, final Connection con, final Object object) { 
    STRUCT struct = null; 
    Object[] params = new Object[1]; 
    params[0] = "This is test text"; 


    struct = getJDBCStructureObject(structDescriptor, con, params); 
    return struct; 
    } 


    private STRUCT getJDBCStructureObject(final StructDescriptor structDescriptor, final Connection con, 
     final Object[] params) { 
    STRUCT struct = null; 
    try { 
     struct = new STRUCT(structDescriptor, con, params); 
    } catch (SQLException e) { 
     LOG.error("Error in creating JDBC structure Object.", e); 
    } 
    return struct; 
    } 

    private ARRAY getJDBCArrayObject(final ArrayDescriptor arrayDescriptor, final Connection con, 
     final STRUCT[] structs) { 
    ARRAY oracleArray = null; 
    try { 
     oracleArray = new ARRAY(arrayDescriptor, con, structs); 
    } catch (SQLException e) { 
     LOG.error("Error in creating JDBC Array Object.", e); 
    } 
    return oracleArray; 
    } 

Но это работает, только если я пошлю по крайней мере один объект в списке. Если я попытаюсь отправить пустой список, я получаю следующую ошибку.

Caused by: org.springframework.jdbc.UncategorizedSQLException: Could not set parameters for mapping: 

У меня есть googled и нашел решение для использования ниже.

preparedStatement.setNull(i, Types.ARRAY); 

Но это тоже не сработало. Я также попытался определить DEFAULT NULL в моей хранимой процедуре, но это также не сработало. Пробовал и ниже.

preparedStatement.setArray(i, new ARRAY(arrayDescriptor, con, new STRUCT[]{null})); 

Это привело к исключению неправильных или неверных аргументов. Также попробовал следующее.

preparedStatement.setNull(i,Types.Array, "ABC_OBJECT_LIST"); 

Идите ниже ошибки.

Caused by: org.springframework.jdbc.BadSqlGrammarException: 
### Error querying database. Cause: java.sql.SQLException:ORA-06550: line 1, column 7: 
PLS-00306: wrong number or types of arguments in call to 'PROCESSAUTOTICKETING' 
ORA-06550: line 1, column 7: 
PL/SQL: Statement ignored 

Я гугле, но в основном были найдены решения для примитивных типов, таких как Integer, String и т.д., но не Перечислите и решение я нашел (SetNull) не работает.

Я использую MyBatis (аннотация) для вызова хранимой процедуры. Есть ли способ справиться с этим, чтобы отправить null в качестве ввода или может быть пустым списком хранимой процедуры.

+0

Ваша последняя попытка - не пустой массив, это массив с одним элементом, который является нулевым. Вы не показали, как «oracleArray» определяется/заполняется, когда он пуст. И ваш 'setNull' пропускает тип массива. [Это может быть полезно] (http://stackoverflow.com/a/29356270/266304). –

+0

@AlexPoole: Поскольку я пытался много вариантов, я просто попробовал отправить массив с нулевым элементом, чтобы проверить, работает ли это, но это не так :(. Я обновил свой вопрос с помощью фрагмента кода для обработчика. то есть любая помощь. Спасибо – Raghav

+0

Вы попробовали свой второй как «подготовленныйStatement.setNull (i, Types.ARRAY,« ABC_OBJECT_LIST »);'? Вы не сказали, какая ошибка, полученная от этого. –

ответ

0

Я, наконец, разрешил это после длинного списка удачных и пробных вариантов. Решение заключалось в определении NULL в Oracle Type, как показано ниже.

create or replace TYPE "ABC_OBJECT" AS OBJECT (
    ticket_no VARCHAR2(50) NULL, 
); 

create or replace TYPE "ABC_OBJECT_LIST" IS TABLE OF ABC_OBJECT NULL; 

Это позволяет передавать нуль в массиве в typehandler ниже

preparedStatement.setArray(i, new ARRAY(arrayDescriptor, con, null)); 

Это позволяет прохождение нуля в хранимую процедуру, если список пуст в Java коде.

Надеюсь, это экономит время.