JDBC - Oracle 数组下标越界异常

14

我在尝试向Oracle表插入一行时遇到了异常。 我正在使用适用于Oracle 11的ojdbc5.jar。 这是我正在尝试的SQL:

INSERT INTO rule_definitions(RULE_DEFINITION_SYS,rule_definition_type,
rule_name,rule_text,rule_comment,rule_message,rule_condition,rule_active,
rule_type,current_value,last_modified_by,last_modified_dttm,
rule_category_sys,recheck_unit,recheck_period,trackable)
VALUES(RULE_DEFINITIONS_SEQ.NEXTVAL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)

我遇到了以下异常。任何帮助都将不胜感激。

java.ljava.lang.ArrayIndexOutOfBoundsException: 15
at oracle.jdbc.driver.OracleSql.computeBasicInfo(OracleSql.java:950)
    at oracle.jdbc.driver.OracleSql.getSqlKind(OracleSql.java:623)
    at oracle.jdbc.driver.OraclePreparedStatement.(OraclePreparedStatement.java:1212)
    at oracle.jdbc.driver.T4CPreparedStatement.(T4CPreparedStatement.java:28)
    at oracle.jdbc.driver.T4CDriverExtension.allocatePreparedStatement(T4CDriverExtension.java:68)
    at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:3059)
    at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:2961)
    at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:5874)
    at org.jboss.resource.adapter.jdbc.WrappedConnection.prepareStatement(WrappedConnection.java:232)
    at com.gehcit.platform.cds.common.util.db.DBWrapper.executeInsertOracleReturnPK(DBWrapper.java:605)

我认为你应该粘贴你正在执行此SQL的代码。 - Vinko Vrsalovic
7个回答

27
在 Oracle Metalink(Oracle的支持网站 - 注释ID 736273.1)中,我发现这是JDBC适配器中的一个错误(版本为10.2.0.0.0至11.1.0.7.0),当您使用超过7个位置参数调用preparedStatement时,JDBC将抛出此错误。
如果您可以访问Oracle Metalink,则一种选择是前往该网站并下载提到的补丁程序。
另一个解决方案是使用命名参数而不是位置参数进行工作。
INSERT INTO rule_definitions(RULE_DEFINITION_SYS,rule_definition_type,
rule_name,rule_text,rule_comment,rule_message,rule_condition,rule_active,
rule_type,current_value,last_modified_by,last_modified_dttm,
rule_category_sys,recheck_unit,recheck_period,trackable)
VALUES(RULE_DEFINITIONS_SEQ.NEXTVAL,:rule_definition_type,
:rule_name,:rule_text,:rule_comment,:rule_message,:rule_condition,:rule_active,
:rule_type,:current_value,:last_modified_by,:last_modified_dttm,
:rule_category_sys,:recheck_unit,:recheck_period,:trackable)

然后使用

preparedStatement.setStringAtName("rule_definition_type", ...)

等等,以设置命名绑定变量用于此查询。


3
除非需要返回生成的密钥,否则它能正常工作。但至少我仍然会收到这个错误。我正在使用Spring的模板: KeyHolder keyHolder = new GeneratedKeyHolder(); SqlParameterSource paramSource = new BeanPropertySqlParameterSource(item); simpleJdbcTemplate.getNamedParameterJdbcOperations().update(sql, paramSource, keyHolder, new String[] { "id" });有什么想法吗? - Anton Kuzmin
Metalink补丁在某些特定情况下仍无法修复该漏洞。例如,此查询既不适用于已打补丁的ojdbc,也不适用于最新的ojdbc版本(11.2.0.1.0):select 1 from dual where 1 in (?,?,?,?,?,?,?,?) and 1=:foo然而,这个查询却能够正常工作: select 1 from dual where 1 in (?,?,?,?,?,?,?) and 1=:foo结论:不要混合使用位置参数和命名参数,以避免出现这种特定问题。 - Misha
@Raimonds,你能提供一下Oracle Metalink的URL吗?我该如何下载补丁?如何使用该补丁?除了上述提到的方法,还有其他解决方案吗? - Kamlesh Kanazariya

1
我正在使用MyBatis + Oracle + Spring + Maven。如果有8个或以上的参数,则会出现相同的错误"ArrayIndexOutOfBoundsException"。
在pom中将版本ojdbc6更改为ojdbc14。
    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc14</artifactId>
        <version>10.2.0.3.0</version>
    </dependency>

它运行成功了。


1
所有剩下的就是说你需要在你的pom文件中引用一个仓库,但这对我来说是有效的。 - Thialyson Martins

0

没有看到代码,我唯一能想到的就是检查每个连接是否以线程安全的方式被访问。Oracle驱动程序通常非常稳定。我见过奇怪的内部错误只有在你有多个线程访问同一个连接实例并对其进行奇怪的操作时才会出现。它们不是线程安全的,应该保持每个线程一个连接。


0

如果我理解正确,您创建了一个带有15个占位符的预处理语句。因此,您需要将包含15个参数值的数组传递给调用。也许您错过了其中一个或添加了多余的一个?


我认为这是多余的一个。 - Fred

0

看起来你传递了错误数量的参数。你应该传递15个,但你可能发送了16个或14个。


0

嗯,除非我的鼠标光标计数有误,否则您正在尝试将16个值插入15个列中。

尝试在SQLPlus*中执行相同的操作,您应该会收到ORA-00913:太多的值错误。


根据我的计算,语句中的值和列数是匹配的。 - Dave Costa

0

当您无法访问oracle.jdbc.PreparedStatement类(并被迫使用不支持方法#setXXXAtName()的java.sql.PreparedStatement)时,使用命名参数的建议解决方案不是一个选项。

我已经使用了PreparedStatement和GeneratedKeyHolder方法来传递必需的值(幸运的是少于7个),并使用返回的生成主键来发出简单的SQL更新以获取其余的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接