Java Oracle11g:使用简单的jdbc调用将数组作为输入参数传递给Oracle存储过程

Java Oracle11g:使用简单的jdbc调用将数组作为输入参数传递给Oracle存储过程,java,oracle,stored-procedures,jdbc,oracle11g,Java,Oracle,Stored Procedures,Jdbc,Oracle11g,我有以下存储过程: PROCEDURE test( p_a IN VARCHAR_ARRAY, p_b VARCHAR_ARRAY, p_c IN VARCHAR_ARRAY, p_d VARCHAR_ARRAY , p_e NUMBER_ARRAY, p_f IN NUMBER_ARRAY, p_Results OUT SYS_REFCURSOR); 在哪里 TYPE NUMBER_ARRAY IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; typ

我有以下存储过程:

PROCEDURE test( p_a IN VARCHAR_ARRAY, p_b VARCHAR_ARRAY, p_c IN VARCHAR_ARRAY, 
p_d VARCHAR_ARRAY , p_e NUMBER_ARRAY,  p_f IN NUMBER_ARRAY, p_Results OUT SYS_REFCURSOR);
在哪里

TYPE NUMBER_ARRAY IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
type VARCHAR_ARRAY IS TABLE OF VARCHAR2(1000) INDEX BY BINARY_INTEGER;
现在,我正试图使用
SimpleJdbcCallOperations
从java调用这个过程

SimpleJdbcCallOperations jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                .withSchemaName(schema)
                .withCatalogName(catalog);
final Result result = (Result) response.results().get(Constants.Dal.RESULTS);
final RowMapper<T> rowMapper = result.mapper();
jdbcCall.returningResultSet(Constants.Dal.RESULTS, rowMapper);
SqlParameterSource in = new SqlParameterSource();
in.addValue("p_a", new SqlArrayValue(a), Types.ARRAY, "VARCHAR_ARRAY");
in.addValue("p_b", new SqlArrayValue(b), Types.ARRAY, "VARCHAR_ARRAY");
in.addValue("p_c", new SqlArrayValue(c), Types.ARRAY, "VARCHAR_ARRAY");
in.addValue("p_d", new SqlArrayValue(d), Types.ARRAY, "VARCHAR_ARRAY");
in.addValue("p_e", new SqlArrayValue(e), Types.ARRAY, "NUMBER_ARRAY");
in.addValue("p_f", new SqlArrayValue(f), Types.ARRAY, "NUMBER_ARRAY");

final List<T> results = (List<T>) jdbcCall.executeObject(response.clazz(), in);
SimpleJDBCAllOperations jdbcCall=new SimpleJdbcCall(jdbcTemplate)
.withSchemaName(模式)
.带目录名(目录);
最终结果=(Result)response.results().get(Constants.Dal.results);
final RowMapper RowMapper=result.mapper();
returningResultSet(Constants.Dal.RESULTS,行映射器);
SqlParameterSource in=新的SqlParameterSource();
在.addValue(“p_a”,新的SqlArrayValue(a),Types.ARRAY,“VARCHAR_数组”);
在.addValue(“p_b”,新的SqlArrayValue(b),Types.ARRAY,“VARCHAR_数组”);
在.addValue(“p_c”,新的SqlArrayValue(c),Types.ARRAY,“VARCHAR_数组”);
在.addValue(“p_d”,新的SqlArrayValue(d),Types.ARRAY,“VARCHAR_数组”);
在.addValue(“p_e”,新的SqlArrayValue(e),Types.ARRAY,“NUMBER_数组”);
在.addValue(“p_f”,新的SqlArrayValue(f),Types.ARRAY,“NUMBER_数组”);
最终列表结果=(List)jdbcCall.executeObject(response.clazz(),in);
其中a、b、c、d为字符串[],e、f为BigDecimal[]

但我得到了以下错误:

CallableStatementCallback;SQL[{调用的未分类SQLException 测试(?,,,,,,,,,,)}];SQL状态[99999];错误代码[17059]; 无法转换为内部表示: [Ljava.lang.String;@5dadd44e;嵌套异常为 java.sql.SQLException:无法转换为内部表示形式: [Ljava.lang.String;@5dadd44e”

我尝试过很多组合。使用List代替[],double代替BigDecimal,不同的类型,…任何帮助都将不胜感激

更新:

类型是在存储过程中声明的,我尝试通过指定模式和包名来添加参数,如下所示:
in.addValue(“p_a”,new SqlArrayValue(a),Types.ARRAY,“SCHEMANAME.PACKAENAME.VARCHAR_ARRAY”);

Oracle版本:11.2.0.3.0(11g)


@Lukas Eder在评论中提到,只有12c支持关联数组。如何在11g中实现这一点?

找到了解决方案。在传递Java数组之前,必须将Java数组转换为Oracle本机数组

MapSqlParameterSource inParams = new MapSqlParameterSource();    
try {
    DataSource ds = jdbcTemplate.getDataSource();
    Connection conn = DataSourceUtils.getConnection(ds);
    OracleConnection oracleConnection = null;
    if (conn.isWrapperFor(OracleConnection.class))
        oracleConnection = conn.unwrap(OracleConnection.class);

    ARRAY aArrayValue = oracleConnection.createARRAY("VARCHAR_ARRAY", a.toArray());
    ARRAY bArray = oracleConnection.createARRAY("VARCHAR_ARRAY", b.toArray());
    ARRAY cArray = oracleConnection.createARRAY("VARCHAR_ARRAY", c.toArray());
    ARRAY dArray = oracleConnection.createARRAY("VARCHAR_ARRAY", d.toArray());
    ARRAY eArray = oracleConnection.createARRAY("NUMBER_ARRAY", e.toArray());
    ARRAY fArray = oracleConnection.createARRAY("NUMBER_ARRAY", f.toArray());

    inParams.addValue("p_a", aArrayValue);
    inParams.addValue("p_b", bArray);
    inParams.addValue("p_c", cArray);
    inParams.addValue("p_d", dArray);
    inParams.addValue("p_e", eArray);
    inParams.addValue("p_f", fArray);

} catch (SQLException e) {
    e.printStackTrace();
}

您使用的是什么Oracle版本?因为在12c之前,您无论如何都无法将关联数组绑定到JDBC…这些类型是在架构级别声明的(即使用
创建或替换类型…
)或者它们是在一个包中声明的?@LukeWoodward-这在过程中,但我尝试通过指定模式、包名来添加参数,如:
in.addValue(“p_a”,新的SqlArrayValue(a),Types.ARRAY,“SCHEMANAME.PACKAENAME.VARCHAR_数组”);
@LukasEder-我使用的是11.2.0.3.0.(11g)。如何在11g中实现同样的效果?在答案中添加一点非常重要,即始终需要关闭数据源连接才能将其返回池连接!
conn.close();
否则,您将导致连接泄漏!