【问题标题】:Issue while facing calling oracle stored procedure from Java using JDBC TEMPLATE使用 JDBC TEMPLATE 从 Java 调用 oracle 存储过程时出现问题
【发布时间】:2021-03-02 14:26:33
【问题描述】:

实际上,对于以下问题,我已经坚持了很长时间。 有没有人通过 Java 实现了 Oracle 存储过程调用,我实现了但得到以下错误'invalid column type 16 error'

"stack_trace":"org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; SQL [{call POST_CYCLE_TFO_STAT_PKG.INSERT_CYCLE_STATUS(?, ?, ?, ?)}] 的未分类 SQLException;SQL 状态 [99999];错误代码 [17004 ]; 列类型无效:16;嵌套异常为 java.sql.SQLException:列类型无效: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

我的程序语法是:

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

而我的 Java 代码如下:

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

任何人都可以就此问题分享任何指示,这将非常有帮助。 谢谢!提前

【问题讨论】:

  • 只是猜测 -- `Types.VARCHAR` 是为 VARCHAR2 参数添加的类型。我对java一无所知。但除了这个问题,我看不到任何其他问题。
  • 是的,Varchar for Varchar2 in java

标签: java oracle jdbctemplate


【解决方案1】:

这里的主要问题是Oracle JDBC Driver doesn't support passing booleans into Stored Procedures

您可以使用 neat 技巧来传递 IN 布尔参数,如 other answer 中所述,但这不适用于 IN OUT 参数。

因此,作为一种解决方法,您必须使用 INT 参数而不是 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;   
/

通过将Types.BOOLEAN 替换为Types.INTEGER,您的代码将更简单

Oracle 12.2 更新

正如here 所示,Oracle 12.2 支持 PLSQL_BOOLEAN 的本机绑定。

应用于原程序insert_cycle_status,工作解决方案如下:

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

【讨论】:

  • 嗨轰炸机,感谢您分享回复。是的,我们采用了这些方法并将我们的布尔参数更改为 varchar2。感谢您对此的回复。
  • @Varundas04 欢迎您,您也可以接受答案,以便其他人看到这是正确的方法;)
猜你喜欢
  • 1970-01-01
  • 2019-02-14
  • 2021-03-02
  • 1970-01-01
  • 2023-04-03
  • 2011-10-11
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多