Внутренняя ошибка: изображение является изображением коллекции, ожидающим ADT с Oracle

#oracle #spring #jdbc #spring-jdbc

#Oracle #spring #jdbc #spring-jdbc

Вопрос:

Я пытаюсь вызвать хранимую функцию в базе данных Oracle с помощью spring-jdbc.

Это сохраненная функция, которую я пытаюсь вызвать:

 FUNCTION GET_RESOURCE_LIST RETURN RESOURCE_TAB;
  

Далее приводится определение resource_tab

 TYPE RESOURCE_TAB AS TABLE OF TRESOURCE;
  

Далее приводится определение tresource

 TYPE TRESOURCE AS OBJECT(
RESOURCE_ID NUMBER(10,0),
RESOURCE_NAME VARCHAR2(100)
)
  

Вызывающий код

 final SimpleJdbcCall call = new SimpleJdbcCall(idmJdbcTemplate).withFunctionName("get_resource_list").declareParameters(new SqlOutParameter(
        "RETURN", OracleTypes.STRUCT,
        "RESOURCE_TAB",
        new SqlReturnType() {

          @Override
          public Object getTypeValue(CallableStatement cs, int paramIndex, int sqlType, String typeName) throws SQLException {
            final Struct s = (Struct)cs.getObject(paramIndex);
            final Object[] attr = s.getAttributes();
            return attr[1];
          }             
        }));

call.compile();
final Collection<String> resources = call.executeFunction(Collection.class);
  

Последним является трассировка стека, которую я получаю:

 org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{? = call WVUID.IDM_REPO_MANUAL.GET_RESOURCE_LIST()}]; SQL state [99999]; error code [17001]; Internal Error: Image is a collection image,expecting ADT; nested exception is java.sql.SQLException: Internal Error: Image is a collection image,expecting ADT
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:969)
    at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1003)
    Truncated. see log file for complete stacktrace

Caused By: java.sql.SQLException: Internal Error: Image is a collection image,expecting ADT
    at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
    at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:133)
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:199)
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:263)
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:271)
    Truncated. see log file for complete stacktrace
> 
    at org.springframework.jdbc.core.JdbcTemplate$5.doInCallableStatement(JdbcTemplate.java:1015)
    at org.springframework.jdbc.core.JdbcTemplate$5.doInCallableStatement(JdbcTemplate.java:1)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:953)
    ... 62 more
  

Комментарии:

1. Какая версия Oracle? Какая версия драйвера JDBC?

2. Oracle 11G и драйверы на Weblogic 10.3.2.0, которые, я бы предположил, одинаковы.

Ответ №1:

У меня такая же проблема, и я потратил день, чтобы ее исправить. Думая об ошибке «Изображение является изображением коллекции», вместо

OracleTypes.STRUCT это должно быть OracleTypes.ARRAY .

О вашем методе getTypeValue (…) Я не могу сказать, правильно это или нет, но я покажу, как анализировать результирующий набор (возможно, это и другой способ, пожалуйста, напишите это):

 @Override
public Object getTypeValue(CallableStatement cs, int paramIndex,
        int sqlType, String typeName) throws SQLException {

    ARRAY struct = (ARRAY) cs.getObject(paramIndex);

    ResultSet rs = struct.getResultSet();

    while (rs.next()) {
        Object rowIndex = rs.getObject(1);
        oracle.sql.STRUCT row = (oracle.sql.STRUCT) rs.getObject(2);
        if (row != null) {
            Object[] cols = row.getAttributes();
            System.out.print(rowIndex   ": ");
            for (Object col : cols) {
                System.out.print(col   " ");
            }
            System.out.println();
        }
    }

    return "construct your data structure above and return here";
}
  

другой способ заключается

     @Override
public Object getTypeValue(CallableStatement cs, int paramIndex,
        int sqlType, String typeName) throws SQLException {

    ARRAY array = (ARRAY) cs.getObject(paramIndex);

    Object[] rows = (Object[])array.getArray();

    for(Object row : rows){
        Object[] cols = ((oracle.sql.STRUCT)row).getAttributes();
        for (Object col : cols) {
            System.out.print(col   " ");
        }
        System.out.println();

    }

    return "construct your data structure above and return here";
}
  

Комментарии:

1. Я больше не работаю в том месте, где я пытался заставить код работать, поэтому я не могу проверить этот ответ, но это кажется наиболее вероятным решением.

2. У меня та же проблема, и это не неправильный тип объекта: System.out.println(cs.GetObject(paramIndex) выдает мне oracle.sql.STRUCT@<hash>.

Ответ №2:

Проблема заключается в объявлении выходного параметра

 final SimpleJdbcCall call = new SimpleJdbcCall(idmJdbcTemplate).withFunctionName("get_resource_list").declareParameters(new SqlOutParameter(
    "RETURN", OracleTypes.STRUCT,
    "RESOURCE_TAB",
    new SqlReturnType() <etc>
  

Возвращаемый тип ( TYPE RESOURCE_TAB AS TABLE OF TRESOURCE ) — это не OracleTypes.STRUCT (который зарезервирован для типов объектов), а OracleTypes.ARRAY .