1
votes

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

1
Just guessing -- ` Types.VARCHAR` is type added for VARCHAR2 parameter. I have no idea about java. but except for this issue, I am not able to see any other. - Popeye
yes, Varchar for Varchar2 in java - Varundas04

1 Answers

0
votes

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()