You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SqlParameterSource插入27列数据至数据库表时触发数组越界异常

解决NamedParameterJdbcTemplate插入27列数据时的ArrayIndexOutOfBoundsException问题

问题背景

我在使用NamedParameterJdbcTemplate向包含27列的Oracle数据库表插入数据时,遇到了ArrayIndexOutOfBoundsException,错误源自Oracle JDBC驱动的SQL解析阶段。以下是我的代码配置和错误信息:

代码片段

参数构建:

SqlParameterSource parameters = new MapSqlParameterSource() 
    .addValue("Id", 12345678) 
    .addValue("packageId", info.getIrocPkgId()) 
    .addValue("isAsgn", 1) 
    .addValue("startTm", info.getStartTm()) 
    .addValue("endTm", info.getEndTm()) 
    .addValue("type", ConstantVal.TASK) 
    .addValue("note", ConstantVal.ETA + ":" + info.getEta()) 
    .addValue("fdbk", ConstantVal.EMPTY) 
    .addValue("sCnt", 1) 
    .addValue("aCd", ConstantVal.ETA) 
    .addValue("isAuto", 1) 
    .addValue("dfltStartTm", info.getStartTm()) 
    .addValue("dfltEndTm", info.getEndTm()) 
    .addValue("aInfo", ConstantVal.EMPTY) 
    .addValue("stat", ConstantVal.ACTIVE) 
    .addValue("cnclTask", ConstantVal.ZERO) 
    .addValue("asgnNbr", ConstantVal.EMPTY) 
    .addValue("priInd", ConstantVal.ZERO) 
    .addValue("ovlpMatchNbr", ConstantVal.EMPTY) 
    .addValue("attchIds", ConstantVal.EMPTY) 
    .addValue("aType", ConstantVal.EMPTY) 
    .addValue("lInd", ConstantVal.ZERO) 
    .addValue("pAsgn", ConstantVal.ZERO) 
    .addValue("rId", ConstantVal.EMPTY) 
    .addValue("bInd", ConstantVal.EMPTY) 
    .addValue("createDtTm", new Timestamp((new Date()).getTime())) 
    .addValue("updatedDtTm", ConstantVal.EMPTY);

int nb = namedParameterJdbcTemplate.update(insertRecords, parameters, keyHolder, new String[] { "ID" });

SQL配置(beans.xml):

<bean id="insertRecords" class="java.lang.String" scope="prototype">
    <constructor-arg type="java.lang.String" value=" INSERT INTO XYZ ( ID, PACKAGE_ID, IS_ASGN, START_TM, END_TM, TYPE, NOTE, FDBK, S_CNT, A_CD, IS_AUTO, DFLT_START_TM, DFLT_END_TM, A_INFO, STAT, IS_CNCL_TASK, ASGN_NBR, PRI_ASGN_IND, OVLP_MATCH_NBR, A_IDS, ASGN_TYPE, LOCK_IND, P_ASGN, R_ID, B_IND, CREATED_DT_TM, UPDATED_DT_TM ) VALUES ( :Id, :packageId,:isAsgn,:startTm,:endTm,:type,:note,:fdbk,:sCnt,:aCd,:isAuto,:dfltStartTm,:dfltEndTm,:aInfo, :stat,:cnclTask,:asgnNbr,:priInd,:ovlpMatchNbr,:attchIds,:aType,:lInd,:pAsgn,:rId, :bInd,:createDtTm,:updatedDtTm) " />
</bean>

错误栈

java.lang.ArrayIndexOutOfBoundsException
at oracle.jdbc.driver.OracleSql.computeBasicInfo(OracleSql.java:950)
at oracle.jdbc.driver.OracleSql.getSqlKind(OracleSql.java:623)
at oracle.jdbc.driver.OraclePreparedStatement.<init>(OraclePreparedStatement.java:1212)
at oracle.jdbc.driver.T4CPreparedStatement.<init>(T4CPreparedStatement.java:28)
at oracle.jdbc.driver.T4CDriverExtension.allocatePreparedStatement(T4CDriverExtension.java:68)
at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:3140)
at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:3042)
at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:6022)
at oracle.jdbc.OracleConnectionWrapper.prepareStatement(OracleConnectionWrapper.java:679)
at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.pmiPrepareStatement(WSJdbcConnection.java:5071)
at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.prepareStatement(WSJdbcConnection.java:4946)
at org.springframework.jdbc.core.PreparedStatementCreatorFactory$PreparedStatementCreatorImpl.createPreparedStatement(PreparedStatementCreatorFactory.java:231)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:638)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:943)
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:344)

解决方案

这个错误通常是Oracle JDBC驱动在解析SQL语句或处理参数时出现的问题,以下是几个可行的排查和解决步骤:

1. 修复SQL语句中的占位符格式

你的SQL语句中部分占位符之间没有空格(比如:packageId,:isAsgn),虽然语法上合法,但旧版本的Oracle驱动可能在解析时出现索引越界问题。建议给所有占位符之间添加空格,同时格式化SQL提升可读性:

INSERT INTO XYZ ( 
    ID, PACKAGE_ID, IS_ASGN, START_TM, END_TM, TYPE, NOTE, FDBK, 
    S_CNT, A_CD, IS_AUTO, DFLT_START_TM, DFLT_END_TM, A_INFO, STAT, 
    IS_CNCL_TASK, ASGN_NBR, PRI_ASGN_IND, OVLP_MATCH_NBR, A_IDS, 
    ASGN_TYPE, LOCK_IND, P_ASGN, R_ID, B_IND, CREATED_DT_TM, UPDATED_DT_TM 
) VALUES ( 
    :Id, :packageId, :isAsgn, :startTm, :endTm, :type, :note, :fdbk, 
    :sCnt, :aCd, :isAuto, :dfltStartTm, :dfltEndTm, :aInfo, :stat, 
    :cnclTask, :asgnNbr, :priInd, :ovlpMatchNbr, :attchIds, 
    :aType, :lInd, :pAsgn, :rId, :bInd, :createDtTm, :updatedDtTm 
)

2. 检查参数与数据库列的类型匹配

注意到你给updatedDtTm参数传入的是ConstantVal.EMPTY(推测是空字符串),但数据库列UPDATED_DT_TM是日期类型。Oracle的日期列无法接受空字符串,这会导致驱动解析时出错。应该传入null而非空字符串:

.addValue("updatedDtTm", null)

同时检查其他参数的类型,比如LOCK_IND、PRI_ASGN_IND等列如果是数字类型,确保传入的ConstantVal.ZERO是数字而非字符串。

3. 升级Oracle JDBC驱动版本

这个错误在Oracle JDBC驱动的旧版本(比如11g的某些版本)中是已知问题,升级到稳定的新版本(比如12.2.0.1或更高)可以解决这类解析bug。如果使用Maven,更新依赖:

<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>12.2.0.1</version>
</dependency>

4. 验证KeyHolder的使用合理性

你在update方法中指定了keyHolder和new String[] { "ID" },但代码中你手动传入了ID的值(12345678)。如果ID不是自增列,不需要使用KeyHolder来获取生成的键,移除这两个参数试试:

int nb = namedParameterJdbcTemplate.update(insertRecords, parameters);

如果ID确实是自增列,确保数据库配置了自动生成策略,并且参数中不要手动传入Id的值。


内容的提问来源于stack exchange,提问作者KVNS_JavaLearner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:13:00