如何通过simplejdbccall将VARRAY(oracle PL / SQL)参数传递给过程?

时间:2020-06-30 15:57:03

标签: java oracle stored-procedures plsql simplejdbccall

这是VARRAY类型:

CREATE TYPE NUM_ARR IS VARRAY(3) OF NUMBER(0)
;

这是过程

PROCEDURE REGISTER_CONSENT(P_IPS_ACC_IBAN IN VARCHAR2,
                           P_IPS_BANK_BIC IN VARCHAR2,
                           P_STATUS_ID IN NUMBER,
                           P_PERMS IN NUM_ARR,
                           P_EXP_DATE IN DATE)
    IS
BEGIN

    FOR PERM_ID in P_PERMS.first ..P_PERMS.last
        LOOP
            INSERT INTO MLB_TEST.IPS_OB_CONSENT_PERMISSION(ID, CONSENT_ID, PERMISSION_ID, EXPIRATION_DATE)
            VALUES (IPS_OB_CONSENT_PERMISSION_SEQ.nextval,
                    IPS_OB_CONSENT_SEQ.currval,
                    PERM_ID,
                    P_EXP_DATE);
        END LOOP;

END;

这是simplejdbccall(java)

        SimpleJdbcCall caller = new SimpleJdbcCall(dataSource);
    caller.withSchemaName("MLB_TEST")
            .withCatalogName("MLB_OB")
            .withProcedureName("REGISTER_CONSENT")
            .declareParameters(new SqlParameter("P_PERMS", Types.ARRAY, "NUM_ARR"));
    MapSqlParameterSource param = new MapSqlParameterSource()
            .addValue("P_IPS_ACC_IBAN", consent.getIban())
            .addValue("P_IPS_BANK_BIC", consent.getBankBic())
            .addValue("P_STATUS_ID", consent.getConsentStatusId())
            .addValue("P_PERMS", consent.getPermissionsIdList(), Types.ARRAY, "NUM_ARR")
            .addValue("P_EXP_DATE", consent.getExpirationDate());
    caller.execute(param);

这是我得到的错误: 原因:java.sql.SQLException:无法转换为内部表示形式:[Ljava.lang.Integer; @ 40f5407d 在oracle.sql.ARRAY.toARRAY(ARRAY.java:301)

我尝试过

  • 整数数组Ex:新的整数[3];
  • 链接列表Ex:新的LinkedList <>();
  • int数组Ex:新的int [] {1,2,3};

没有任何效果,每次都出现相同的错误。

1 个答案:

答案 0 :(得分:0)

不幸的是,您需要一些特定于供应商的魔术才能使它与JDBC一起使用(不特定于Spring JDBC)。

这是我们使用的名为OracleSqlArrayValue的类。尽管它可以正确地解开连接,但它基本上是从已失效的Spring JDBC扩展library中删除的。由于导入了OracleConnection,在编译期间您将需要在类路径中使用Oracle JDBC驱动程序。

我不久前还将以下大部分内容发布到了here

import java.sql.Connection;
import java.sql.SQLException;

import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.core.support.AbstractSqlTypeValue;

import oracle.jdbc.OracleConnection;

public class OracleSqlArrayValue<T> extends AbstractSqlTypeValue {
    private T[] values;
    private String defaultTypeName;

    public OracleSqlArrayValue(T[] values) {
        this.values = values;
    }

    public OracleSqlArrayValue(T[] values, String defaultTypeName) {
        this.values = values;
        this.defaultTypeName = defaultTypeName;
    }

    @Override
    protected Object createTypeValue(Connection conn, int sqlType,
            String typeName) throws SQLException {

        if (typeName == null && defaultTypeName == null) {
            throw new InvalidDataAccessApiUsageException(
                    "No type named defined. Instantiate class with default type name.");
        }

        if (!conn.isWrapperFor(OracleConnection.class)) {
            throw new InvalidDataAccessApiUsageException(
                    "Unable to unwrap OracleConnection. Ensure you are connecting to an Oracle DB.");
        }

        return conn.unwrap(OracleConnection.class).createOracleArray(
                typeName != null ? typeName : defaultTypeName, values);
    }
}

然后您将像这样使用它。

SimpleJdbcCall caller = new SimpleJdbcCall(dataSource);
caller.withSchemaName("MLB_TEST")
        .withCatalogName("MLB_OB")
        .withProcedureName("REGISTER_CONSENT")
        .declareParameters(new SqlParameter("P_PERMS", Types.ARRAY, "NUM_ARR"));
MapSqlParameterSource param = new MapSqlParameterSource()
        .addValue("P_IPS_ACC_IBAN", consent.getIban())
        .addValue("P_IPS_BANK_BIC", consent.getBankBic())
        .addValue("P_STATUS_ID", consent.getConsentStatusId())
        .addValue("P_PERMS", new OracleSqlArrayValue<Integer>(consent.getPermissionsIdList(), "NUM_ARR"))
        .addValue("P_EXP_DATE", consent.getExpirationDate());
caller.execute(param);