问题背景:有一BUG,调用平台执行存储过程接口报错,最终通拷贝oracle11g里面的ojdbc6.jar驱动到服务器里解决
也就是尽量保证服务器驱动和数据库一致,不知道是谁替换了不同版本的驱动,但是为什么不同版本会报错?下面让我们
一探究竟。
看看下面2个测试场景:
1.重现问题 ojdbc6.jar(版本号:11.2.0.1.0)
调用存储过程代码片段:
cs = con.prepareCall("CALL TEST_PROCEDURE(?)");
cs.setObject("I_P1", "ABCD");
cs.execute();
结果报错:java.sql.SQLException: 试图设置未出现在 SQL 中的参数名: I_P1
和测试服务器报错一致。
2.解决问题 ojdbc6.jar(11.2.0.3.0)
驱动换成ORACLE11g的驱动后就正常了。
查资料,JDK帮助文档里面只定义了JDBC操作的接口,各个驱动具体去实现,经过反编译看代码发现
具体附件的四个驱动如下:
ojdbc14.jar 9.0.2.0.0 没有实现直接抛异常
ojdbc14.jar 10.2.0.2.0,ojdbc6.jar 11.2.0.3.0 支持场景1的写法。
ojdbc6.jar 11.2.0.1.0 不支持场景1的写法,正确的写法如下:
cs = con.prepareCall("CALL TEST_PROCEDURE(
:I_P1)");//不支持?作为占位符
cs.setObject("I_P1", "ABCD");
cs.execute();
总结:
到这里问题就搞清楚了,是因为我们在调用接口的时候没有按照接口参数格式传入。
该问题还有一个办法就是把CALL TEST_PROCEDURE(
?)这种改为CALL TEST_PROCEDURE(
:I_P1)这种。
太坑了,不是一般都是用‘?’的吗,继续看,查看
CallableStatement prepareCall(
String sql)该接口说明
‘sql
- 可以包含一个或多个?参数占位符的SQL语句...’接口说明里说参数要用‘?’号作为占位
符,但是现实是很残酷的,有人就不遵守规范。
所以,为了保证我们的程序健壮性建议调用接口
的,而且测试附件四个驱动都是没问题的。