-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
About the Bug...
-
I have checked that this issue has not already been reported.
-
I have confirmed this bug exists on the latest version of MyBatis.
-
I have confirmed this bug reproduces without 3rd party extensions (e.g. mybatis-plus).
Database Version
MySQL 5.7.27
JDBC Driver Version
MySQL Connector/J 5.1.47
Issue Description
MyBatis Version: 3.4.6 → 3.5.6
Database Version and JDK Version is not so important.
After upgrading MyBatis from version [3.4.6]to [3.5.6], batch insert operations that previously worked correctly now throw the exception: "Too many keys are generated. There are only 1 target objects.".
Error Details:
- Exception Type: org.apache.ibatis.executor.ExecutorException
- Error Message: Too many keys are generated. There are only 1 target objects. You either specified a wrong 'keyProperty' or encountered a driver bug like Error occurred when I try to "INSERT INTO ~ ON DUPLICATE KEY UPDATE" with useGeneratedKeys. #1523.
- Impact: Batch insert operations fail completely, affecting data persistence functionality.
Steps to Reproduce:
- Configure MyBatis with batch executor
- Perform batch insert operation with multiple entities
- Operation fails with the specified exception
Code Example:
ps: this code works well when version is 3.4.6.
repository:
List<XXXDTO> entities;// get some entities
Map<String, Object> param = Maps.newHashMap();
param.put("list", entities);
XXXMapper.batchInsert(param);// use Map as param
mapper:
int batchInsert(Map<String, Object> param);
xml:
<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>
Expected Behavior:
- Batch insert should complete successfully
- All records should be inserted with proper key generation
- Behavior should be consistent with previous version
Actual Behavior:
- Exception thrown: "Too many keys are generated. There are only 1 target objects."
- No records are inserted
- Batch operation fails completely
Key Code Comparison:
version 3.5.6:
private static Collection<?> collectionize(Object param) {
if (param instanceof Collection) {
return (Collection<?>) param;
} else if (param instanceof Object[]) {
return Arrays.asList((Object[]) param);
} else {
// when param is Map, enter this method
return Arrays.asList(param);
}
}
version 3.4.6:
private Collection<Object> getParameters(Object parameter) {
Collection<Object> parameters = null;
if (parameter instanceof Collection) {
parameters = (Collection) parameter;
} else if (parameter instanceof Map) {
// when param is Map, enter this method
Map parameterMap = (Map) parameter;
if (parameterMap.containsKey("collection")) {
parameters = (Collection) parameterMap.get("collection");
} else if (parameterMap.containsKey("list")) {
// parse list in Map
parameters = (List) parameterMap.get("list");
} else if (parameterMap.containsKey("array")) {
parameters = Arrays.asList((Object[]) parameterMap.get("array"));
}
}
if (parameters == null) {
parameters = new ArrayList<Object>();
parameters.add(parameter);
}
return parameters;
}
new version seems not support Map as param any longer.
Suggested Fix:
Fix param parse logic in Jdbc3KeyGenerator
or
maybe throw a clearer exception like Map not support as param
for example:
private static Collection<?> collectionize(Object param) {
if (param instanceof Collection) {
return (Collection<?>) param;
} else if (param instanceof Object[]) {
return Arrays.asList((Object[]) param);
} else if (param instanceof Map){
throw new ExecutorException("Map is no longer supported as parameter.");
} else {
return Arrays.asList(param);
}
}
About your report...
-
I did not use images 🖼️ for showing text information (code, error, etc.).
-
I checked the Preview and my report looks awesome! 👍