简体   繁体   中英

Caused by: java.sql.SQLException: ORA-06550: line 1, column 7: PLS-00306: wrong number or types of arguments in call to 'PR_SP_FAHMI'

I have java file which use to execute Store Procedure by using SimpleJdbc like in the below code:

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {SQLException.class, Exception.class })
public void executeSPForInsertData(DataSource ds,String procedureName,Map<String, Object> inputParameter){
    //PARAMS.PKG_PARA_UPLD_VAL.PR_SP_FAHMI
    String[] inParam = inputParameter.keySet().toArray(new String[0]);
    SqlParameter[] in = new SqlParameter[inParam.length];
    String[] buff = new String[inParam.length * 2];
    SimpleJdbcCall jdbcCall = new SimpleJdbcCall(paramsDataSourceBean)
                              .withProcedureName(procedureName)
                              .withoutProcedureColumnMetaDataAccess()
                              .useInParameterNames(buff).declareParameters(in);
    String[] path = procedureName.split(".");
    if (path.length >= 2) {
        jdbcCall.withSchemaName(path[0]);
        jdbcCall.withCatalogName(path[1]);
        jdbcCall.withProcedureName(path[2]);
    }
    Map<String,Object> outputParameter = jdbcCall.execute(inputParameter);
}

and this is my stored procedure

PROCEDURE PR_SP_FAHMI (P_T_TABLE_UPLD_EXCEL IN PARAMS.EXCEL)
   is 
  P_LOGID VARCHAR2(255);
BEGIN
BEGIN
  INSERT INTO PARAMS.EMPTY
  SELECT 
  C.PARA_OBJT_GROUP            ,
  C.PARA_OBJT_CODE             ,
  C.PARA_PROD_MATRIX_ID        ,
  C.PARA_PROD_CHANNEL_ID       ,
  C.PARA_PROD_SALES_GROUP_ID   ,
  C.PARA_CUST_GROUP            ,
  C.PARA_SLS_THROUGH_ID        ,
  C.ACTIVE                     
  FROM TABLE(P_T_TABLE_UPLD_EXCEL) C;
  EXCEPTION
            WHEN NO_DATA_FOUND THEN
                NULL;
            WHEN OTHERS THEN
                RAISE_APPLICATION_ERROR(-20001, 'ERROR-' || SQLERRM);
        END;
END PR_SP_FAHMI;

this is declaration type excel

CREATE OR REPLACE TYPE EXCEL AS TABLE OF PARAMS.T_OBJECT_FROM_EXCEL

and this is declaration type T_OBJECT_FROM_EXCEL

CREATE OR REPLACE TYPE "T_OBJECT_FROM_EXCEL" FORCE AS OBJECT (
  para_objt_group            VARCHAR2(3),
  para_objt_code             VARCHAR2(3),
  para_prod_matrix_id        VARCHAR2(5),
  para_prod_channel_id       VARCHAR2(3),
  para_prod_sales_group_id   VARCHAR2(5),
  para_cust_group            VARCHAR2(3),
  para_sls_through_id        VARCHAR2(2),
  active                     NUMBER(1)
)

When i run the code, i have error this

Caused by: java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'PR_SP_FAHMI'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

I have search in internet to solve this issue by looking similliar error but still can't solve my problem.

To use Spring to call an Oracle stored procedure that takes a parameter whose type is a table of an object, there are a couple of things that need to be done.

Firstly, you need to create an Java class that corresponds to the Oracle object type T_OBJECT_FROM_EXCEL . It needs to implement the SQLData interface. It will look something like the following (please feel free to change the field names as appropriate):

import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;

public class ExcelRow implements SQLData {

    private String objectGroup;
    private String objectCode;
    private String prodMatrixId;
    private String prodChannelId;
    private String prodSalesGroupId;
    private String prodCustGroup;
    private String slsThroughId;
    private boolean active;

    // ... constructor, getters and setters omitted ...

    @Override
    public String getSQLTypeName() {
        return "PARAMS.T_OBJECT_FROM_EXCEL";
    }

    @Override
    public void readSQL(SQLInput sqlInput, String typeName) throws SQLException {
        throw new SQLException("This has not been implemented");
    }

    @Override
    public void writeSQL(SQLOutput sqlOutput) throws SQLException {
        sqlOutput.writeString(this.objectGroup);
        sqlOutput.writeString(this.objectCode);
        sqlOutput.writeString(this.prodMatrixId);
        sqlOutput.writeString(this.prodChannelId);
        sqlOutput.writeString(this.prodSalesGroupId);
        sqlOutput.writeString(this.prodCustGroup);
        sqlOutput.writeString(this.slsThroughId);
        sqlOutput.writeInt(this.active ? 1 : 0);
    }
}

The SQLData interface has three methods, getSQLTypeName() , readSQL() and writeSQL() . getSQLTypeName() returns the name of the Oracle type we are mapping to, and writeSQL() writes the data in an ExcelRow object to the given output object sqlOutput . The order of the fields that we write must match the order they are declared in T_OBJECT_FROM_EXCEL . readSQL() is used to convert a T_OBJECT_FROM_EXCEL object returned from the database into an ExcelRow , but we're only interested in sending values to the database, not receiving them from the database, so for brevity I've just implemented it to throw an exception.

Secondly, you need to adjust the code that calls the stored procedure. Your method executeSPForInsertData seems to be somewhat generic in that it takes a stored procedure and an arbitrary map of parameters. Because of the table type parameter, this stored procedure is a little awkward to call in a generic way, so we'll write a method intended specifically for this one stored-procedure call:

    public void executeSPForInsertData(DataSource ds, ExcelRow[] excelRows){
        String parameterName = "P_T_TABLE_UPLD_EXCEL";
        SqlParameter[] parameterTypes = { new SqlParameter(parameterName, OracleTypes.ARRAY, "PARAMS.EXCEL") };

        Map<String, Object> parameters =
                Collections.singletonMap(parameterName, new SqlArrayValue<>(excelRows));

        SimpleJdbcCall jdbcCall = new SimpleJdbcCall(ds)
                .withSchemaName("PARAMS")
                .withCatalogName("PKG_PARA_UPLD_VAL")
                .withProcedureName("PR_SP_FAHMI")
                .withoutProcedureColumnMetaDataAccess()
                .declareParameters(parameterTypes);

        jdbcCall.execute(parameters);
    }

We start by declaring the parameter types: there's one parameter and it's an array whose Oracle type is EXCEL in the PARAMS schema. Then we declare the parameter values, ussing a SqlArrayValue to wrap the array of ExcelRow s that we pass in. Finally we set up the stored procedure call and then call it. As the parameter name is used twice, I put it in a local variable.

I gave this a quick test against an Oracle 18c XE database and it worked, in that I could call this stored procedure and have it write data to the database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM