异常日志如下: 
java.lang.ArrayIndexOutOfBoundsException: -32653 
    at 
oracle.jdbc.driver.OraclePreparedStatement.setupBindBuffers(OraclePreparedStatement.java:2673) 
    at 
oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10689) 
    at 
weblogic.jdbc.wrapper.PreparedStatement_oracle_jdbc_driver_T4CPreparedStatement.executeBatch(Unknown Source) 
    at 
org.springframework.jdbc.core.JdbcTemplate$4.doInPreparedStatement(JdbcTemplate.java:763) 
    at 
org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:460) 
    at 
org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:489) 
    at 
org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:754) 
... 
DAO层代码如下:
public void insertAddDeclare(final String lsh, final List data,
final Properties relation) throws BusinessException {
StringBuffer sql = new StringBuffer();
sql.append(" insert into T_ZSSB_SBJFXZMX (SBLSH, SFZHM, GR_ID, XM, ");
sql.append("        YJFE_JE) ");
sql.append(" values (?, ?, ?, ?, ?) "); try {
getJdbcTemplate().batchUpdate(sql.toString(),
new BatchPreparedStatementSetter() { public void setValues(PreparedStatement ps, int index)
throws SQLException {
Map m = (Map) data.get(index);
int i = 0;
ps.setString(++i, lsh);
try {
String card = m.get("SFZHM").toString().trim();
String name = m.get("XM").toString().trim();
String id = relation.getProperty(card);
ps.setString(++i, card);
ps.setString(++i, id.trim());
ps.setString(++i, name);
ps.setString(++i, m.get("ZSXMDM").toString());
} catch (NullPointerException e) {
throw new NullPointerException("第" + index
+ "行、第" + i + "个字段出现空值");
}
} public int getBatchSize() {
return data.size();
} });
} catch (DataAccessException e) {
throw new BusinessException("5003", e.getMessage());
} catch (NullPointerException e) {
throw new BusinessException("6401", e.getMessage());
} catch (NoSuchFieldError e) {
throw new BusinessException("6407", e.getMessage());
}
}我跟了一下JdbcTemplate的batchUpdate方法,出错的地方不在上面回调的方法体内,也就是说上面这段代码没问题。从上面异常日志来看,报错的地方是在jdbc驱动包中某个类的方法里。所以我想知道什么情况下批量更新会发生数组越界?

解决方案 »

  1.   

    在ORACLE论坛中得到如下资料:The 10g driver apparently keeps a global serial number for all parameters in the entire batch, with a "short" variable. So you can have at most 32768 parameters in the batch. I was having the same exception because I have a INSERT statement with 42 parameters and my batches can be as big as 1000 records, so 42000 > 32768 and this overflows to a negative index. I reduced the batch factor to 100 to be safe, and all is well. I guess your update DML should have a larger number of parameters per record, right? (My diagnostic of the bug is just deduction from the symptoms)
    根据上述,你的语句有五个参数,而最大的参数允许为32768,也就是你当前要修改的记录是不是超过了32768/5=6554条记录了? 如果超了,就会取他的补码,也就是负值,取负值时,你的数组下标一定是越界的,你可以在库中查询一下,与要修改的满足条件的记录的总数进行比对一下~~