Oracle DB - Java Ссылка на неинициализированную коллекцию для конкретного пакета - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть Java-объект, который выглядит следующим образом

Class A
{
  private String name;
  private List<B> bList;
}

У меня также есть пользовательские объекты Oracle, определенные для этих Java-объектов.

create type T_B as object
                         (
                            myNumber  number,
                            message   varchar2(4000)
                         );

create type T_B_LIST  as table of T_B;

create type T_A as object
                         (
                           name varchar2(4000),
                           b    T_B_LIST
                         );

create type T_A_LIST  as table of T_A;

Теперь я составил 10 списков A(List<A>), где каждый список содержит 20 элементов и пытается вставить их в БД с помощью процедуры.Таким образом, в основном у меня есть 10 пакетов и всего 200 элементов.

 procedure add(a  in T_A_LIST)
 begin
   for i in 1..a.last loop
     insert into sometable values a(i).name ; 
   end loop;
 end

Проблема в том, что некоторые из пакетов успешно вставляются, но где-то около 6-го пакета pl / sql дает сбой со следующей ошибкой.

ORA-06531: Reference to uninitialized collection

Я использую Java / Spring SQLData класс и java.sql.Struct и java.sql.Array объекты для создания персистентного слоя Java.

Я пробовал разные варианты, такие как вставка целых элементов (200) в один пакет, но это все ещеошибка с той же ошибкой.

public class A  implements SQLData{
    private  String name;

    private List<B> bList;
    private Array bArray;
    @Override
    public String getSQLTypeName() throws SQLException {

        return  "T_A";
    }
    @Override
    public void readSQL(SQLInput stream, String typeName) throws SQLException {
        // TODO Auto-generated method stub

    }
    @Override
    public void writeSQL(SQLOutput stream) throws SQLException {
        stream.writeString(name);
        stream.writeArray(bArray);
    }

    // setters and getters
}


public class B implements SQLData {

    private Long myNumber;
    private String message;

    @Override
    public String getSQLTypeName() throws SQLException {
        return "T_B";

    }

    @Override
    public void readSQL(SQLInput stream, String typeName) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public void writeSQL(SQLOutput stream) throws SQLException {
        stream.writeLong(myNumber);
        stream.writeString(message);

    }

}

// And the DAO logic
class Test
{
    List<B> bList; // A List of B objects
    List<A> aList;  // A list of A objects

    Array array = dbUtil.getOracleArray("T_B_LIST",
            bList.toArray());
    A a = new A(); 
    a.setBArray(array);
    aList.add(a);

    Array aArray = dbUtil.getOracleArray("T_A_LIST",
            aList.toArray());

    // DeclareParameter
    // call plsql procedure using SimpleJdbcCall giving the aArray as argument.


} 

заранее спасибо

1 Ответ

0 голосов
/ 07 февраля 2019

Вы не опубликовали никакого кода Java / Spring, поэтому я объясняю, почему ошибка возникает только со стороны Oracle.

[TL; DR] Ошибка возникает при передачеNULL значение или коллекция, которая не была инициализирована.Либо убедитесь, что вы всегда передаете не-1006 * инициализированную коллекцию, либо используете выражение TABLE.

Oracle Setup :

CREATE PROCEDURE add_a_list( a  in T_A_LIST )
AS
BEGIN
  FOR i IN 1..a.last LOOP
     INSERT INTO sometable VALUES ( a(i).name ); 
  END LOOP;
END;
/

Запрос1 : передача инициализированной коллекции:

BEGIN
  add_a_list(
    T_A_LIST(
      T_A( 'one',   NULL ),
      T_A( 'two',   T_B_LIST() ),
      T_A( 'three', T_B_LIST( T_B( 3.1, 'message 3.1' ) ) ),
      T_A( 'four',  T_B_LIST( T_B( 4.1, 'message 4.1' ), T_B( 4.2, 'message 4.2' ) ) )
    )
  );
END;
/

Работает так, как ожидалось, поскольку коллекция была инициализирована.

SELECT * FROM sometable;

Выходы:

| NAME  |
| :---- |
| one   |
| two   |
| three |
| four  |

Запрос 2 : передача значения NULL:

BEGIN
  add_a_list( NULL );
END;
/

Возникает исключение:

ORA-06531: Reference to uninitialized collection
ORA-06512: at "FIDDLE_UMPWUWIBMKJJGKGIRJGH.ADD_A_LIST", line 4
ORA-06512: at line 2

Когда процедура достигает цикла FOR и пытаетсянайти значение a.last, где a равно NULL и вызывает исключение.

Запрос 3 : передача неинициализированной коллекции:

DECLARE
  value T_A_LIST;
BEGIN
  add_a_list( value );
END;
/

Выходы:

ORA-06531: Reference to uninitialized collection
ORA-06512: at "FIDDLE_UMPWUWIBMKJJGKGIRJGH.ADD_A_LIST", line 4
ORA-06512: at line 4

Когда процедура достигает цикла FOR и пытается найти значение a.last, где a является неинициализированной коллекцией и вызывает исключение.

db<> fiddle здесь

Настройка Oracle - изменено :

Используйте выражение TABLE():

CREATE PROCEDURE add_a_list( a  in T_A_LIST )
AS
BEGIN
  INSERT INTO sometable ( name )
  SELECT name
  FROM   TABLE( a );
END;
/

Повторное проeries 2 и 3 с измененной процедурой выполняется без исключений и не вставляет никаких строк.

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