【问题标题】:Passing String array into Oracle stored procedure with string_varray type将字符串数组传递到具有 string_varray 类型的 Oracle 存储过程
【发布时间】:2019-02-13 14:19:12
【问题描述】:

我在 Oracle 12c DB 中有一个带有以下签名的存储过程:

create or replace PROCEDURE myproc(param1 IN NUMBER, param2 IN STRING_ARRAY, param3 IN STRING_ARRAY, outparam OUT BOOLEAN) IS

这里的STRING_ARRAY定义如下:

create or replace TYPE STRING_ARRAY AS VARRAY(1000) OF VARCHAR2(4000);

在我的 dao 层中,我通过以下方式调用它:

SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate).withProcedureName("myschema.myproc");


    SqlTypeValue param2ArrayValue = new AbstractSqlTypeValue() {
        protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException {
            ARRAY array = ((OracleConnection) conn).createARRAY("myschema.STRING_ARRAY", param2Values);
            return array;
        }
    };


    SqlTypeValue param3ArrayValue = new AbstractSqlTypeValue() {
        protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException {
            ARRAY array = ((OracleConnection) conn).createARRAY("myschema.STRING_ARRAY", param3Values);
            return array;
        }
    };

    SqlParameterSource inParams = new MapSqlParameterSource().addValue("param1", param1Value)
                                                             .addValue("param2", param2ArrayValue)
                                                             .addValue("param3", param3ArrayValue);

    Map<String, Object> outParams = simpleJdbcCall.execute(inParams);
    logger.info("RetFlag:::::" + outParams.get("outparam"));

我收到以下异常::

org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call myschema.myproc(?, ?, ?, ?)}]; SQL state [99999]; error code [17004]; Invalid column type: 1111; nested exception is java.sql.SQLException: Invalid column type: 1111 
Caused by: java.sql.SQLException: Invalid column type: 1111

我参考了以下链接:: Spring Forum link 1

谁能提供任何解决方案?

【问题讨论】:

    标签: java oracle12c spring-jdbc


    【解决方案1】:

    我已按照以下步骤操作:

    我已将 StoredProcedure OUT 参数的数据类型从布尔值更改为数字:

    create or replace PROCEDURE myproc(param1 IN NUMBER, param2 IN STRING_ARRAY, param3 IN STRING_ARRAY, return_flag OUT NUMBER) IS
    

    通过继承spring-jdbc模块的StoredProcedureclass创建了一个自定义类

    public class MyCustomProcedure extends StoredProcedure{
    
        public MyCustomProcedure(JdbcTemplate jdbcTemplate, String procedureName) {
          super(jdbcTemplate, procedureName);
          declareParameter(new SqlParameter("param1", Types.NUMERIC));
          declareParameter(new SqlParameter("param2", Types.ARRAY, "STRING_ARRAY"));
          declareParameter(new SqlParameter("param3", Types.ARRAY, "STRING_ARRAY"));
          declareParameter(new SqlOutParameter("return_flag", Types.NUMERIC));
        }
    
        public boolean execute(Long param1, String[] param2, String[] param3) {
           Boolean resultFlag= null;
           BigDecimal outputReturned  = null;
           Map resultMap = null;
           AbstractSqlTypeValue customArrayTypeParam2 = null;
           AbstractSqlTypeValue customArrayParamType3 = null;
    
           try (final Connection connectionWrapper = getJdbcTemplate().getDataSource().getConnection()) {
            customArrayTypeParam2 = new MyCustomOracleArrayType(connectionWrapper, param2);
            customArrayTypeParam3 = new MyCustomOracleArrayType(connectionWrapper, param3);
               resultMap = super.execute(param1, customArrayTypeParam2, customArrayTypeParam3);
             }catch(Exception e){
                e.printStackTrace();
             }
    
            if (MapUtils.isNotEmpty(resultMap)) {
                 outputReturned = (BigDecimal) resultMap.get("return_flag");
            if ((Integer.valueOf(outputReturned.intValue())).equals(Integer.valueOf(1))) {
                resultFlag= true;
            }
        } else {
            resultFlag= false;
        }
        return resultFlag;
       }
     }
    

    请在下面找到我的 CustomOracleArrayType 类

    public class MyCustomOracleArrayType extends AbstractSqlTypeValue {
        private final Connection oracleCon;
        private final Object[] values;
    
        public MyCustomOracleArrayType(final Connection oracleCon, final Object[] values) {
            this.oracleCon = oracleCon;
            this.values = values;
        }
    
        @Override
        protected Object createTypeValue(final Connection con, final int sqlType, final String typeName)
                throws SQLException {
            Array array =  ((OracleConnection)oracleCon).createOracleArray("STRING_ARRAY", values);
            return array;
        }
      }
    

    我在 Spring 配置文件中进行了以下修改以注入 MyCustomProcedure 类:

    <bean id="myCustomProcedure" class="mypackage.MyCustomProcedure">
       <constructor-arg index="0" type="org.springframework.jdbc.core.JdbcTemplate" ref="jdbcTemplate"/>
       <constructor-arg index="1" type="java.lang.String" value="myproc"/>
    </bean>
    <bean id="myService" class="mypackage.MyServiceImpl">
      <property name="myCustomProcedure" ref="myCustomProcedure"/>
    </bean>
    <!--jdbcTemplate already defined in my spring config file along with dataSource -->
    

    就是这样,我只是从我的服务层以传统方式调用 MyCustomProcedure 的execute() 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-25
      • 2012-03-30
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 2012-11-23
      • 1970-01-01
      • 2021-08-18
      相关资源
      最近更新 更多