java - 将空列表发送到存储过程

标签 java oracle stored-procedures mybatis empty-list

我在 oracle 中创建了一个自定义类型,如下所示。

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:

我用谷歌搜索并找到了使用下面的解决方案。

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

我用谷歌搜索,但主要找到了原始类型(如整数、字符串等)的解决方案,但没有找到列表,而且我找到的解决方案(setNull)不起作用。

我正在使用MyBatis(annotation)来调用存储过程。有什么方法可以处理这个问题,将 null 作为输入发送,或者可能是存储过程的空白列表。

最佳答案

经过一长串的点击和试用选项后,我终于解决了这个问题。解决方案是在 Oracle Type 中定义 NULL,如下所示。

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;

这允许在类型处理程序中的数组中传递 null,如下所示

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

如果 Java 代码中列表为空,则可以将 null 传递给存储过程。

希望这可以节省某人的时间。

关于java - 将空列表发送到存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38638999/

相关文章:

mysql - 没有索引的大数据分组

sql - Oracle 中的 View 和物化 View 有什么区别?

mysql - 使用一个事件执行两个过程

Java无法解析的日期异常

java - SwingWorker要更新TreeModel吗?

sql - Oracle LIMIT 和 1000 列限制

MySQL 过程未执行

java - 如何制作一个 TextView 来绕过 Android 中的其他 TextView?

java.io.IOException : error=2, 没有那个文件或目录

database - 从 PL/SQL 调用另一个 Oracle 数据库中的过程