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.