Java调用带返回值的Oracle函数遇报错,寻求解决方法
解决Java调用Oracle PL/SQL函数(CLOB入参/出参)的三类错误
错误1:CallableStatement报「Missing IN or OUT parameter at index:: 2」
原因
调用Oracle函数时必须用? := integ_pkg.insert_order(?)的格式声明返回值占位符,多数情况是漏写返回值绑定或参数顺序搞反,导致驱动无法匹配参数位置。
正确实现代码
String sql = "{ ? = call integ_pkg.insert_order(?) }"; try (Connection conn = getConnection(); CallableStatement cs = conn.prepareCall(sql)) { // 1. 注册返回参数(CLOB类型) cs.registerOutParameter(1, OracleTypes.CLOB); // 2. 绑定输入参数:字符串直接用setString,驱动会自动转CLOB String inputContent = "{\"orderId\":\"ORD001\",\"amount\":100}"; cs.setString(2, inputContent); // 大文本场景可手动创建CLOB对象 // Clob inputClob = conn.createClob(); // inputClob.setString(1, inputContent); // cs.setClob(2, inputClob); cs.execute(); // 读取返回的CLOB结果 Clob resultClob = cs.getClob(1); String result = resultClob.getSubString(1, (int) resultClob.length()); System.out.println(result); } catch (SQLException e) { e.printStackTrace(); }
错误2:StoredProcedureQuery传JSONObject报「Type cannot be null」
原因
JPA的StoredProcedureQuery无法直接识别JSONObject类型,必须先将其转为字符串,再显式指定参数的SQL类型为CLOB,否则框架无法推断参数类型导致报错。
正确实现代码
EntityManager em = getEntityManager(); StoredProcedureQuery query = em.createStoredProcedureQuery("integ_pkg.insert_order"); // 注册函数返回参数(Oracle函数返回值位置固定为1) query.registerStoredProcedureParameter(1, String.class, ParameterMode.OUT); // 注册输入参数,显式指定SQL类型为CLOB query.registerStoredProcedureParameter(2, String.class, ParameterMode.IN); query.setHint("javax.persistence.storedProcedure.sqlType.2", OracleTypes.CLOB); // 将JSONObject转为字符串传入 JSONObject inputObj = new JSONObject(); inputObj.put("orderId", "ORD001"); inputObj.put("amount", 100); query.setParameter(2, inputObj.toString()); query.execute(); // 获取返回结果 String result = (String) query.getOutputParameterValue(1); System.out.println(result);
错误3:StoredProcedureQuery传String报ORA-06550参数不匹配
原因
直接传String时,JPA默认映射为VARCHAR2类型,但函数期望的是CLOB类型,当字符串长度超过VARCHAR2最大限制(通常4000字符)时,就会触发参数类型不匹配错误,必须显式指定参数为CLOB类型。
正确实现代码
EntityManager em = getEntityManager(); StoredProcedureQuery query = em.createStoredProcedureQuery("integ_pkg.insert_order"); // 注册返回参数 query.registerStoredProcedureParameter(1, String.class, ParameterMode.OUT); // 注册输入参数,强制指定SQL类型为CLOB query.registerStoredProcedureParameter(2, String.class, ParameterMode.IN); query.setHint("javax.persistence.storedProcedure.sqlType.2", OracleTypes.CLOB); // 直接传入大文本字符串,框架会自动转为CLOB String inputStr = "你的超长订单JSON内容..."; query.setParameter(2, inputStr); query.execute(); String result = (String) query.getOutputParameterValue(1); System.out.println(result);
内容的提问来源于stack exchange,提问作者franco
相关产品推荐
相关产品推荐

