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

MyBatis执行truncate table二次调用报Index 0 out of bounds异常

问题:MyBatis执行TRUNCATE后多次插入出现索引越界错误

配置与代码

XML映射配置

<update id="truncateTable">
        truncate TABLE ${tableName}
</update>

业务方法代码

public void flushNeoReceivePayment() throws IOException {
    dwsTableSqlMapper.truncateTable("dwd_table");
    dwsTableSqlMapper.insertSomething1();
    dwsTableSqlMapper.insertSomething1();
}

insertSomething1方法用于插入部分数据

问题现象

  • 首次调用flushNeoReceivePayment方法完全正常
  • 第二次调用时抛出错误,日志如下:
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5368e1af] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@1571751346 wrapping com.mysql.cj.jdbc.ConnectionImpl@72168258] will not be managed by Spring
==>  Preparing: truncate dwd_table
==> Parameters: 
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5368e1af]
2024-09-10 13:32:27.685 ERROR --- [nio-3009-exec-2] c.z.z.c.exceptions.GlobalExceptionHandle : 
org.springframework.dao.TransientDataAccessResourceException: 
### Error updating database.  Cause: java.sql.SQLException: Index 0 out of bounds for length 0
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: truncate dwd_table
### Cause: java.sql.SQLException: Index 0 out of bounds for length 0
; Index 0 out of bounds for length 0; nested exception is java.sql.SQLException: Index 0 out of bounds for length 0
  • 特殊场景测试结果:
    • 只调用一次insertSomething1时,方法执行正常:
      public void flushNeoReceivePayment() throws IOException {
          dwsTableSqlMapper.truncateTable("dwd_table");
          dwsTableSqlMapper.insertSomething1();
      } // 执行正常
      
    • 将truncate替换为delete语句时,无论调用多少次插入方法都不会报错

解决方案

原因分析

核心问题是TRUNCATE的DDL特性+非事务场景下MyBatis连接复用导致的参数绑定异常:

  1. TRUNCATE是DDL语句,执行后会自动提交事务并重置连接状态;
  2. 非事务模式下,MyBatis可能复用TRUNCATE执行后的连接,但该连接的参数绑定缓冲区状态与后续多次插入操作的逻辑冲突,引发索引越界错误。

可行解决办法

  1. 给方法添加事务管理
    在flushNeoReceivePayment方法上添加@Transactional注解,让Spring管控整个方法的事务生命周期,确保连接在同一事务内正常复用:

    @Transactional
    public void flushNeoReceivePayment() throws IOException {
        dwsTableSqlMapper.truncateTable("dwd_table");
        dwsTableSqlMapper.insertSomething1();
        dwsTableSqlMapper.insertSomething1();
    }
    
  2. 强制TRUNCATE执行后刷新缓存
    在XML映射中为TRUNCATE语句添加flushCache="true"属性,强制MyBatis执行后刷新缓存并重新获取连接,避免状态异常的连接被复用:

    <update id="truncateTable" flushCache="true">
            truncate TABLE ${tableName}
    </update>
    
  3. 替换TRUNCATE为DELETE(业务允许时)
    如测试所示,使用DELETE FROM dwd_table替代TRUNCATE可规避该问题,但注意DELETE是DML语句,不会重置自增主键,且大数据量下性能弱于TRUNCATE,需根据业务场景选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:20:13