简体   繁体   中英

Issue while facing calling oracle stored procedure from Java using JDBC TEMPLATE

Actually i am stuck with quite a time now regarding the below issue. Does anyone has implemented Oracle Stored procedure calling through Java, i have implemented but getting the below error 'invalid column type 16 error'

"stack_trace":"org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call POST_CYCLE_TFO_STAT_PKG.INSERT_CYCLE_STATUS(?, ?, ?, ?)}]; SQL state [99999]; error code [17004]; Invalid column type: 16; nested exception is java.sql.SQLException: Invalid column type: 16\\r\\n\\tat org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:89)\\r\\n\\tat org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)\\r\\n\\tat org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)\\r\\n\\tat org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1443)\\r\\n\\tat org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1108)\\r\\n\\tat org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1147)\\r\\n \\tat org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:412)\\r\\n\\tat org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:372)\\r\\n\\tat org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:198)\\r\\n\\tat com.mastercard.settlment.axon.payment.request.status.dao.AxonPaymentRequestCycleEventStatusDao.getCycleEventStatus(AxonPaymentRequestCycleEventStatusDao.java:46)\\r\\n\\tat

my procedure syntax is:

PROCEDURE insert_cycle_status (SETTLEMENT_DATE_MANUAL   IN     DATE,
                                  DEBUG_FLAG               IN OUT BOOLEAN,
                                  ERROR_INFO                  OUT VARCHAR2,
                                  RESULT                      OUT BOOLEAN);

And my Java code is like below:

SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate)
                            .withoutProcedureColumnMetaDataAccess()
                            .withProcedureName(CYCLE_EVENT_STATUS_PROCEDURE)
                            .declareParameters(new SqlParameter("SETTLEMENT_DATE_MANUAL", Types.DATE))
                            .declareParameters(new SqlParameter("DEBUG_FLAG", Types.BOOLEAN))
                            .declareParameters(new SqlOutParameter("ERROR_INFO", Types.VARCHAR))
                            .declareParameters(new SqlOutParameter("RESULT", Types.BOOLEAN));
            
            SqlParameterSource in = new MapSqlParameterSource()
                            .addValue("SETTLEMENT_DATE_MANUAL", null)
                            .addValue("DEBUG_FLAG", 1);
            
            Map<String, Object> result = call.execute(in);

Can anyone share any pointers on this, regarding the issue, it will be really helpful. Thanks! In Advance

The main problem here is that Oracle JDBC Driver doesn't support passing booleans into Stored Procedures

You could use a neat trick to pass an IN boolean parameter as described in the other answer but this will not work for IN OUT parameters.

So as a workaround you'll have to wrap the stored procedure using the INT parameters instead of BOOLEAN

-- wrapper procedure 
create or replace PROCEDURE insert_cycle_status2 (SETTLEMENT_DATE_MANUAL   IN     DATE,
                                  DEBUG_FLAG               IN OUT INT, /* Wrap BOOLEAN with INT */
                                  ERROR_INFO                  OUT VARCHAR2,
                                  RESULT                      OUT INT) as
 v_DEBUG_FLAG BOOLEAN := (DEBUG_FLAG != 0);
 v_RESULT BOOLEAN := (RESULT != 0);
begin
  insert_cycle_status(SETTLEMENT_DATE_MANUAL,v_DEBUG_FLAG, ERROR_INFO, v_RESULT);
  if v_RESULT  THEN 
     RESULT := 1;
  else
    RESULT := 0;
  end if;
  if v_DEBUG_FLAG  THEN 
     DEBUG_FLAG := 1;
  else
    DEBUG_FLAG := 0;
  end if;         
end;   
/

Than your code will work simple by substituting both Types.BOOLEAN with Types.INTEGER

Update for Oracle 12.2

As demonstrated here the Oracle 12.2 support native binding of PLSQL_BOOLEAN.

Applied on the the original procedure insert_cycle_status the working solution would be as follows:

// works in Oracle Release 12.2+
stmt = con.prepareCall("{ call insert_cycle_status(?,?,?,?)}") 
stmt.setDate(1, java.sql.Date.valueOf("2020-11-21"));
stmt.setObject(2,true,oracle.jdbc.OracleTypes.PLSQL_BOOLEAN)  /* BOOLEAN parameter */
stmt.registerOutParameter(2,oracle.jdbc.OracleTypes.PLSQL_BOOLEAN)
stmt.registerOutParameter(3,Types.VARCHAR)
stmt.registerOutParameter(4,oracle.jdbc.OracleTypes.PLSQL_BOOLEAN)
stmt.execute()

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