3

这是在以下位置发布的问题的延续: Java program to pass List of Bean to a oracle stored procedure - 一次性传递整个列表,而不是一个接一个地附加对象

我一直在尝试增强上述链接位置中提到的存储过程,并且在实现中感到困惑。而不是 VARCHAR2 作为过程的输出,我现在想要返回 NUM_ARRAY 作为过程的输出。你能帮我实现在我的java代码中读取NUM_ARRAY的逻辑吗?通常使用 Map out = super.execute(inParams); 返回输出。我现在如何将 NUM_ARRAY 提取到我的 bean 中?

The source code implementation is as follows.

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import oracle.jdbc.OracleTypes;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.SqlTypeValue;
import org.springframework.jdbc.object.StoredProcedure;

public class RevPrdBrkDwnSP extends StoredProcedure{

    private final Logger log = Logger.getLogger(this.getClass().getName());

    public RevPrdBrkDwnSP(DataSource dataSource, String storeProcName) {

        // Run the Parent
        super(dataSource, storeProcName);

        // Declare the Parameter Details
        declareParameter(new SqlParameter("IN_ARRAY", OracleTypes.ARRAY, "****.PROD_PRCT_BRKDWN_TYPE_ARRAY"));
        declareParameter(new SqlOutParameter("OUT_ARRAY", OracleTypes.ARRAY, "****.PROD_PRCT_BRKDWN_TYPE_ARRAY"));

        // Compile the SP
        compile();
    }

    public boolean execute(final RevAppViewBean appViewBean$Session, final DataSource dataSource) throws Exception {
        boolean returnVal = false;
        Map<String, Object> inParams = new HashMap<String, Object>();
        log.info("Setting up the Store Procedure Params");

        inParams.put("IN_ARRAY", new SqlTypeValue() {
            public void setTypeValue(PreparedStatement cs, int index, int sqlType, String typeName) throws SQLException {
                Connection con = cs.getConnection();
                ArrayDescriptor des = ArrayDescriptor.createDescriptor("****.PROD_PRCT_BRKDWN_TYPE_ARRAY", con);
                ARRAY a = new ARRAY(des, con, appViewBean$Session.getExcelRecLst().toArray());
                cs.setObject(1, (Object)a);
            }
        });

        inParams.put("OUT_ARRAY", identifier); // what should the identifier be ?????????

        if (log.isDebugEnabled()) {
            log.debug("Executing the **** Store Procedure ");
        }

        Map out = super.execute(inParams); // how to get the same array as value ?????? 

        log.info("output size is --------------------->>>>>>>>>> "+out.size());
        for(Object o : out.keySet()){
            log.info((String)out.get(o));
            returnVal = Boolean.parseBoolean((String)out.get(o));
        }

        if (log.isDebugEnabled()) {
            log.info("Output from **** Store Procedure :" + out);
        }

        return returnVal;
    }
}

更新: 使用 Spring Data JDBC Extension 后,必须更改源代码以适应下面粘贴的新响应,但调用 bean.getAttributes() 方法时仍然存在连接问题。看起来需要找到一种在连接关闭之前不关闭连接或访问值的方法。

Map out = super.execute(inParams);
        log.info("output size is --------------------->>>>>>>>>> "+out.size()); //prints the actual value

        Object[] idOutArraz = (Object[])out.get("OUT_ARRAY");

        log.info("size of returnValue is "+idOutArraz.length); //prints the right number of results

        for(int i= 0; i<idOutArraz.length;i++){
            Object[] attrs = null;
            Struct bean = (Struct) idOutArraz[i];
            attrs = bean.getAttributes();
            if (attrs != null) {
                System.out.println(Arrays.asList(attrs));
            }
        } 
4

2 回答 2

11

经过很多尝试和错误后用不同的方法回答。在尝试实施很多解决方案后,Callable 语句对我有用。看起来像是一种解决方法,但欢迎任何解决实际实施的解决方案。

请在下面找到实现的工作副本。

import java.math.BigDecimal;
import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import oracle.jdbc.OracleTypes;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.STRUCT;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.StoredProcedure;

import com.****.****.****.ExcelListenerBean;
import com.****.****.****.RevAppViewBean;

public class RevPrdBrkDwnSP extends StoredProcedure{

    private final Logger log = Logger.getLogger(this.getClass().getName());

    private  Connection con = null;
    private DataSource ds = null;

    public RevPrdBrkDwnSP(DataSource dataSource, String storeProcName) throws SQLException {

        // Run the Parent
        super(dataSource, storeProcName);

        con = dataSource.getConnection();
        ds = dataSource;

        if (log.isInfoEnabled()) {
            log.info("Stored Procedure Name : "+ storeProcName);
        }
        // Declare the Parameter Details
        declareParameter(new SqlParameter("IN_ARRAY", OracleTypes.ARRAY, "****.PROD_PRCT_BRKDWN_TYPE_ARRAY"));
        declareParameter(new SqlOutParameter("OUT_ARRAY", OracleTypes.ARRAY, "****.PROD_PRCT_BRKDWN_TYPE_ARRAY"));

        // Compile the SP
        compile();
    }


    public List<ExcelListenerBean> execute(final RevAppViewBean appViewBean$Session, DataSource dataSource) throws Exception {
        dataSource = ds;
        List<ExcelListenerBean> beans = new ArrayList<ExcelListenerBean>();

        log.info("Setting up the Store Procedure Params");

        String getDBUSERByUserIdSql = "{call ****.PRCS_PROD_PRCT_BRKDWN_ENTRIES(?,?)}";
        CallableStatement cs = con.prepareCall(getDBUSERByUserIdSql);

        ArrayDescriptor des = ArrayDescriptor.createDescriptor("PBAREV.PROD_PRCT_BRKDWN_TYPE_ARRAY", con);
        ARRAY a = new ARRAY(des, con, appViewBean$Session.getExcelRecLst().toArray());
        cs.setObject(1, (Object)a);

        cs.registerOutParameter(2, OracleTypes.ARRAY, "****.PROD_PRCT_BRKDWN_TYPE_ARRAY");

        if (log.isDebugEnabled()) {
            log.debug("Executing the PBAREV Store Procedure ");
        }

        cs.execute();
        log.info("Executed ****.PRCS_PROD_PRCT_BRKDWN_ENTRIES... Processing values to beans"); 

        Array arr = cs.getArray(2);

        Object[] objArr = (Object[]) arr.getArray();
        for(int i=0; i<objArr.length;i++){
            STRUCT st = (STRUCT)objArr[i];
            ExcelListenerBean bean = new ExcelListenerBean();
            Object[] obj = st.getAttributes();
            bean.setPrntGdwIdN(((BigDecimal)obj[1]).longValue());
            bean.setChldGdwIdN(((BigDecimal)obj[2]).longValue());
            bean.setChldAsetPrcntN(Double.valueOf(String.valueOf(obj[4])));
            bean.setStatus(String.valueOf(obj[8]));
            bean.setStatusMessage(String.valueOf(obj[9]));
            beans.add(bean);
        }

        if (log.isDebugEnabled()) {
            log.info("Finised processing SP output values to ExcelListenerBeans");
        }

        return beans;
    }
}
于 2013-06-09T12:52:41.970 回答
3

在 Oracle 方面,您的代码可能如下所示:

全局类型声明:

CREATE OR REPLACE TYPE NUM_ARRAY AS TABLE OF NUMBER;

存储过程:

CREATE OR REPLACE PROCEDURE PROD_PRCT_BRKDWN_TYPE_ARRAY (
   in_array    IN     NUM_ARRAY,
   out_status  OUT    VARCHAR2)
IS
...

纯 JDBC 代码(带有一些 Oracle 特定部分):

Connection con = ...;
CallableStatementcs = con.prepareCall(" ... ");
ArrayDescriptor des = ArrayDescriptor.createDescriptor("PBAREV.PROD_PRCT_BRKDWN_TYPE_ARRAY", con);

Integer[] idArray = new Integer[50000];

// fill the array of integers here
for (int i = 0; i < idArray.length; i++)
    idArray[i] = ....;

ARRAY a = new ARRAY(des, con, idArray);
cs.setObject(1, (Object)a);
cs.registerOutParameter(2, OracleTypes.ARRAY, "PBAREV.PROD_PRCT_BRKDWN_TYPE_ARRAY");

cs.execute();

ARRAY outArray = (ARRAY)cs.getArray(2);
Integer[] idOutArraz = (Integer[])outArray.getArray();

我没有测试过代码。但它应该给你一个想法。

更新:

对于到 Spring Framework 的转换,您可能希望查看包含该类的Spring Data JDBC Extensionorg.springframework.data.jdbc.support.oracle.SqlReturnArray项目并声明您的参数,如下所示:

declareParameter(new SqlOutParameter("OUT_ARRAY", Types.ARRAY,
    "PBAREV.PROD_PRCT_BRKDWN_TYPE_ARRAY", new SqlReturnArray()));

我想知道Mapexecute方法的 out 数组包含什么,因为文档没有说明任何内容。

于 2013-06-06T06:44:19.213 回答