Skip to content

fix(extension): support foreach parameters in data change recorder#7133

Open
smf-h wants to merge 3 commits into
baomidou:3.0from
smf-h:fix-data-change-recorder-foreach-params
Open

fix(extension): support foreach parameters in data change recorder#7133
smf-h wants to merge 3 commits into
baomidou:3.0from
smf-h:fix-data-change-recorder-foreach-params

Conversation

@smf-h

@smf-h smf-h commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Related to #7061.

Summary

  • Resolve custom XML foreach insert parameter names such as __frch_item_0.id through BoundSql additional parameters before falling back to the original parameter object lookup.
  • This lets DataChangeRecorderInnerInterceptor record inserted values from foreach item/list data instead of failing to resolve the generated foreach binding names.
  • Add regression tests for foreach insert additional parameters across the jsqlparser variants.

Validation

  • git diff --check origin/3.0...HEAD passed.
  • Marker scan on changed files for TODO/FIXME/XXX/debug/focus leftovers found no matches.
  • ./gradlew.bat --version used cached Gradle 8.13.
  • ./gradlew.bat :mybatis-plus-jsqlparser-support:mybatis-plus-jsqlparser:testClasses :mybatis-plus-jsqlparser-support:mybatis-plus-jsqlparser-4.9:testClasses :mybatis-plus-jsqlparser-support:mybatis-plus-jsqlparser-5.0:testClasses --no-daemon --max-workers=1 passed.
  • Focused DataChangeRecorderInnerInterceptorTest execution was attempted, but the local Gradle test worker failed before running tests with ClassNotFoundException: worker.org.gradle.process.internal.worker.GradleWorkerMain.

@smf-h

smf-h commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

补充一个更贴近真实使用链路的复现说明,方便 review。

真实问题场景

业务中常见的写法是自定义 Mapper XML 里用 <foreach> 批量插入:

<insert id="insertUsersByXmlForeach">
    insert into h2user(test_id, name, age, test_type) values
    <foreach collection="list" item="item" separator=",">
        (#{item.testId}, #{item.name}, #{item.age}, #{item.testType})
    </foreach>
</insert>

调用方式类似:

mapper.insertUsersByXmlForeach(Arrays.asList(
    new H2User(id1, "xmlForeachInsertA", AgeEnum.ONE, 1),
    new H2User(id2, "xmlForeachInsertB", AgeEnum.TWO, 1)
));

MyBatis 在解析 <foreach> 后,BoundSql(绑定 SQL)里的 ParameterMapping(参数映射)可能会变成下面这种内部参数名:

__frch_item_0.testId
__frch_item_0.name
__frch_item_0.age
__frch_item_0.testType
__frch_item_1.testId
__frch_item_1.name
__frch_item_1.age
__frch_item_1.testType

这些 __frch_item_0 / __frch_item_1 不是原始 parameterObject(外层参数对象)上的字段,而是 MyBatis 放在 BoundSql.additionalParameters(附加参数)里的 foreach 临时变量。

修复前的问题

DataChangeRecorderInnerInterceptor 之前主要从原始 parameterObject 解析参数值。遇到 __frch_item_0.name 这种 foreach 内部参数名时,可能无法取到真实值,典型表现就是类似下面的异常或变更记录缺失:

Parameter '__frch_item_0' not found. Available parameters are [list, param1]

本 PR 的修复

解析参数值时改为:

  1. 优先从 BoundSql.additionalParameters 读取 MyBatis 生成的 foreach 参数;
  2. 如果不是 additional parameter(附加参数),再回退到原来的 parameterObject 解析逻辑。

这样可以支持 <foreach> 生成的 __frch_item_0.xxx 参数,同时不改变普通非 foreach 场景的行为。

新增真实回归测试

我补充了一个真实链路的集成测试,不再只手动构造 BoundSql

  • H2StudentMapper.insertUsersByXmlForeach(@Param("list") List<H2User> h2Users)
  • H2StudentMapper.xml 中新增真实 <foreach> insert
  • H2UserTest.testDataChangeRecorderWithRealXmlForeachInsert()

测试链路是:

Mapper 方法调用
-> XML <foreach> 动态 SQL
-> MyBatis 生成 BoundSql 和 additionalParameters
-> MybatisPlusInterceptor
-> DataChangeRecorderInnerInterceptor
-> H2 数据库写入

测试断言包括:

  • 批量插入返回 2 行;
  • 两条记录真实写入 H2;
  • DataChangeRecorderInnerInterceptor 捕获到的变更结果中包含 foreach 插入数据的真实字段值。

本地已验证:

./gradlew --no-daemon -Pkotlin.jvm.target.validation.mode=warning :mybatis-plus:test --tests "com.baomidou.mybatisplus.test.h2.H2UserTest.testDataChangeRecorderWithRealXmlForeachInsert"
BUILD SUCCESSFUL

同时 :mybatis-plus:compileTestJava 也已通过。

@smf-h smf-h marked this pull request as draft July 6, 2026 09:51
@smf-h smf-h marked this pull request as ready for review July 6, 2026 14:06
@qmdx qmdx force-pushed the 3.0 branch 5 times, most recently from e24207f to db0b3c4 Compare July 8, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant