【问题标题】:Oracle 11g: Pass array as input parameter to an oracle stored procedure using simple jdbc callOracle 11g:使用简单的 jdbc 调用将数组作为输入参数传递给 oracle 存储过程
【发布时间】:2015-12-09 13:03:51
【问题描述】:

我有以下存储过程:

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);

其中 a,b,c,d 是 String[],e,f 是 BigDecimal[]

但我收到以下错误:

CallableStatementCallback; SQL [{call] 的未分类 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 中实现这一点?

【问题讨论】:

  • 您使用的是哪个 Oracle 版本?因为在 12c 之前,无论如何都不能将关联数组绑定到 JDBC...
  • 这些类型是在模式级别声明的(即使用CREATE OR REPLACE TYPE ...)还是在包中声明?
  • @LukeWoodward - 它在程序中,但我尝试通过指定架构、包名称来添加参数,如下所示:in.addValue("p_a", new SqlArrayValue(a), Types.ARRAY, "SCHEMANAME.PACKAENAME.VARCHAR_ARRAY");
  • @LukasEder - 我正在使用 11.2.0.3.0 .. (11g) 。我如何在 11g 中实现同样的效果?

标签: java oracle stored-procedures jdbc oracle11g


【解决方案1】:

找到了解决方案。在传递它们之前必须将 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();
}

【讨论】:

  • 添加到答案中非常重要,您需要始终关闭数据源连接以将其返回到池连接! conn.close(); 否则会出现连接泄漏!
猜你喜欢
  • 2014-12-26
  • 2011-02-22
  • 2016-02-02
  • 1970-01-01
  • 2012-11-23
  • 1970-01-01
  • 2013-10-24
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多