Why MyBatis Batch Insert Fails After Upgrade and How to Fix It

This article analyzes a MyBatis batch‑insert failure caused by the useGeneratedKeys setting after upgrading from 3.4.6 to 3.5.6, explains the root‑cause in the Jdbc3KeyGenerator, and provides both temporary and permanent solutions with code examples.

Instant Consumer Technology Team
Instant Consumer Technology Team
Instant Consumer Technology Team
Why MyBatis Batch Insert Fails After Upgrade and How to Fix It

1. Introduction

When using MyBatis for batch inserts, the useGeneratedKeys attribute can be set to true to enable automatic back‑filling of database‑generated primary keys, simplifying key retrieval logic and improving development efficiency.

Benefits of useGeneratedKeys=true

Automatic key retrieval : MyBatis calls JDBC.getGeneratedKeys() to obtain auto‑increment IDs without extra SQL.

Simplified code : No need for a separate SELECT LAST_INSERT_ID(); the key is directly populated into the object via keyProperty.

Configurable scope : Can be set globally in settings or locally in a specific mapper XML/annotation.

Database compatibility : Works with databases that support auto‑increment (e.g., MySQL, SQL Server). For databases without this feature (e.g., Oracle), a <selectKey> tag is required.

Reduced key‑retrieval errors : JDBC guarantees atomicity, avoiding concurrency‑related mistakes.

2. Background

The Yili Life system, a core marketing platform, serves millions of daily users. After upgrading MyBatis from 3.4.6 to 3.5.6, the system began throwing ExecutorException with the message “Too many keys are generated…”, causing batch‑insert failures.

3. Impact

Retry mechanism failure : Batch‑insert errors prevent scheduled retry jobs from succeeding.

Data loss risk : Failed records require manual intervention, increasing operational cost.

System stability degradation : Frequent exceptions affect overall database performance and may lead to temporary service outages.

4. Investigation

Environment

SpringBoot 2.3.12.RELEASE, SpringCloud Hoxton.SR12

MyBatis 3.5.6 (upgraded version)

JDK 1.8

Stack trace analysis

Caused by: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: Too many keys are generated. There are only 1 target objects. You either specified a wrong 'keyProperty' or encountered a driver bug like #1523.
    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:96)
    ... (additional stack frames omitted)

The exception originates from Jdbc3KeyGenerator.assignKeys() inside MyBatis.

Relevant code snippets

Service / Repository layer

List<XXXDTO> entities; // data acquisition omitted
Map<String, Object> param = Maps.newHashMap();
param.put("list", entities);
XXXMapper.batchInsert(param);

Mapper interface

int batchInsert(Map<String, Object> param);

XML mapper (original, problematic)

<insert id="batchInsert" keyProperty="id" useGeneratedKeys="true" parameterType="com.xxx.XXXDTO">
    insert into table_name
    <trim prefix="(" suffix=")" suffixOverrides=",">
        column,
    </trim>
    <foreach collection="list" item="item" index="index" separator="," open="values">
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{item.columnName,jdbcType=VARCHAR},
        </trim>
    </foreach>
</insert>

The error occurs only when useGeneratedKeys=true is present and the parameter is a Map containing a list key.

5. Trigger Conditions

Removing useGeneratedKeys=true eliminates the exception.

Using a List parameter directly (instead of a Map) also avoids the error.

6. Fix Example (list‑parameter approach)

Mapper interface

int batchInsert(@Param("list") Collection<XXXDTO> list);

XML mapper

<insert id="batchInsert" keyProperty="id" useGeneratedKeys="true" parameterType="java.util.Collection">
    insert into table_name
    <trim prefix="(" suffix=")" suffixOverrides=",">
        column,
    </trim>
    <foreach collection="list" item="item" index="index" separator="," open="values">
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{item.columnName,jdbcType=VARCHAR},
        </trim>
    </foreach>
</insert>

7. Root‑Cause Analysis

In MyBatis 3.5.6, Jdbc3KeyGenerator.assignKeys() calls collectionize(parameter). When the parameter is a Map, collectionize wraps the whole map as a single element, so the generator expects one target object but receives multiple generated keys, leading to the “Too many keys are generated” exception. The older 3.4.6 version contained special handling for Map (checking keys like list, collection, etc.), which was removed in the newer version.

8. Summary of Findings

The upgrade eliminated Map‑parameter support for useGeneratedKeys, causing the exception in scenarios that rely on that implicit behavior.

9. Solutions

Temporary measures

Replace batch insert with a loop of single inserts (acceptable for low volume or non‑time‑critical data).

Remove useGeneratedKeys=true when the generated key is not needed.

Fundamental fix

Adopt the list‑parameter style shown in section 6 and avoid passing a Map for batch inserts. This aligns with the current MyBatis contract and prevents the bug.

Note: The issue is reported on MyBatis GitHub (issue #3536) and is unlikely to be fixed in future releases, so upgrading further will not resolve it.

10. Recommendations

Perform thorough version‑upgrade research, focusing on breaking changes and bug fixes.

Write unit tests for batch‑insert operations to catch similar regressions early.

Prefer explicit, strongly‑typed parameters (e.g., List<User>) and use @Param annotations to define intent clearly.

Document framework‑level contracts and avoid relying on undocumented internal behaviors.

11. References

Official source code: https://github.com/mybatis

Bug discussion: https://github.com/mybatis/mybatis-3/issues/2375

Issue report: https://github.com/mybatis/mybatis-3/issues/3536

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaMyBatisBatch Insertbug-fixuseGeneratedKeys
Instant Consumer Technology Team
Written by

Instant Consumer Technology Team

Instant Consumer Technology Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.