PLS-00306:从Spring JDBC调用时调用中参数的数量或类型错误

SVa*_*dya 0 privileges spring procedure jdbc

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar  
[{call pkg_name.procedure_name()}]; nested exception is java.sql.SQLException: ORA-06550: line 1,  column 7:
PLS-00306: wrong number or types of arguments in call to 'PROCEDURE_NAME'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Run Code Online (Sandbox Code Playgroud)

我有两个架构-OwnerSchema和AppSchema。我拥有从OwnerSchema到AppSchema的所有程序包的授予执行特权。当我尝试从AppSchema的后端执行任何过程时,便能够执行该过程。当我尝试从Java Spring JDBC执行相同的过程时,出现上述错误。我可以从Java的OwnerSchema执行此过程。

我可以使用AppSchema从Java Spring JDBC应用程序访问所有表。

我已使用以下触发器指向LogOn上的OwnerSchmea。

 CREATE OR REPLACE TRIGGER FINAL_APP_USER.AFTER_LOGON_TRG
    AFTER LOGON ON FINAL_APP_USER.SCHEMA
    BEGIN
      DBMS_APPLICATION_INFO.SET_MODULE(USER, 'Initialized');
    EXECUTE IMMEDIATE 'ALTER SESSION SET current_schema=TEST'; --enter owner
    END;
    /
Run Code Online (Sandbox Code Playgroud)

这是程序调用

SimpleJdbcCall simpleJdbcCall = getSimpleJdbcCall()
                    .withCatalogName("pkg_name").withProcedureName(
                            "procedure_name").returningResultSet(
                            "C_Srf_1", new RowMapper<FinalCountForQuestions>() {
                                public FinalCountForQuestions mapRow(
                                        ResultSet rs, int rowNum)
                                        throws SQLException {

                                    ...

                                    return finalCountForQuestions;
                                }
                            });

            Map<String, Object> mapOfOutputParams = simpleJdbcCall.execute();
Run Code Online (Sandbox Code Playgroud)

SVa*_*dya 5

Spring JDBC模板在调用数据库过程时生成以下查询

SELECT PACKAGE_NAME AS PROCEDURE_CAT,
OWNER AS PROCEDURE_SCHEM,
OBJECT_NAME AS PROCEDURE_NAME,
ARGUMENT_NAME AS COLUMN_NAME,
DECODE(POSITION, 0, 5,
DECODE(IN_OUT, 'IN', 1,
'OUT', 4,
'IN/OUT', 2,
0)) AS COLUMN_TYPE,
DECODE (DATA_TYPE, 'CHAR', 1,
'VARCHAR2', 12,
'NUMBER', 3,
'LONG', -1,
'DATE', 91,
'RAW', -3,
'LONG RAW', -4,
'TIMESTAMP', 93, 
'TIMESTAMP WITH TIME ZONE', -101, 
'TIMESTAMP WITH LOCAL TIME ZONE', -102, 
'INTERVAL YEAR TO MONTH', -103, 
'INTERVAL DAY TO SECOND', -104, 
'BINARY_FLOAT', 100, 'BINARY_DOUBLE', 101, 1111) AS DATA_TYPE,
DECODE(DATA_TYPE, 'OBJECT', TYPE_OWNER || '.' || TYPE_NAME, DATA_TYPE) AS TYPE_NAME,
DECODE (DATA_PRECISION, NULL, DATA_LENGTH,
DATA_PRECISION) AS PRECISION,
DATA_LENGTH AS LENGTH,
DATA_SCALE AS SCALE,
10 AS RADIX,
1 AS NULLABLE,
NULL AS REMARKS,
SEQUENCE,
OVERLOAD,
DEFAULT_VALUE
from ALL_ARGUMENTS
where OWNER like '<USER>' escape  '/'
and OBJECT_NAME like '<PROCEDURE_NAME>' escape '/' 
and PACKAGE_NAME like '<PACKAGE_NAME>' ESCAPE '/'                   
AND (ARGUMENT_NAME LIKE 'C_SRF_1' ESCAPE '/'
OR (ARGUMENT_NAME IS NULL
and DATA_TYPE is not null))
--and
--other arguments
ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME, OVERLOAD, SEQUENCE;
Run Code Online (Sandbox Code Playgroud)

因此,当您使用ApplicationUser调用数据库过程时,它将使用您的ApplicationUser名称进入ALL_ARGUMENTS视图,并且找不到任何参数。因此,解决方案是,当您调用过程时,按以下方式传递所有者的架构名称。

SimpleJdbcCall simpleJdbcCall = getSimpleJdbcCall()
                    .withSchemaName(<OwnerSchema>)
                    .withCatalogName("pkg_name").withProcedureName(
                            "procedure_name").returningResultSet(
                            "C_Srf_1", new RowMapper<FinalCountForQuestions>() {
Run Code Online (Sandbox Code Playgroud)