Deeply nested (3+ levels) result map could cause IllegalArgumentException
See original GitHub issueFor some cases, when parse the mapper xml, it may be have incompleteStatements. The Configuration#buildAllStatements will parse them latter.
But it maybe do twice.
The method org.apache.ibatis.binding.MapperMethod.SqlCommand#resolveMappedStatement:
if (configuration.hasStatement(statementId)) {
return configuration.getMappedStatement(statementId);
}
call the hasStatement method, the validateIncompleteStatements is true, so it will call buildAllStatements method and add the statement to mappedStatements and return true.
then call getMappedStatement, the validateIncompleteStatements is also true, it will call buildAllStatements again.
public MappedStatement getMappedStatement(String id) {
return this.getMappedStatement(id, true);
}
public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
if (validateIncompleteStatements) {
buildAllStatements();
}
return mappedStatements.get(id);
}
it will throw ‘java.lang.IllegalArgumentException’ : Mapped Statements collection already contains…
so I think the code must be:
configuration.getMappedStatement(statementId, **false**)
and I wonder, when the incompleteStatements is build success, why not clear them?
The org.apache.ibatis.session.Configuration#buildAllStatements
/*
* Parses all the unprocessed statement nodes in the cache. It is recommended
* to call this method once all the mappers are added as it provides fail-fast
* statement validation.
*/
It says that the method recommend to be called once, but in the code, there are many place call the org.apache.ibatis.session.Configuration#getMappedStatement(java.lang.String) method, it means if it parse the mapper xml and produce the incompleteStatements, when run the code it will throw already have mapped statement exception?
Issue Analytics
- State:
- Created 6 years ago
- Comments:7 (3 by maintainers)
+1
I cannot understand why it has to be invoked twice. But the root reason is here: This is the snip from
parsePendingResultMaps
(and it’s same structure withparsePendingStatements
The pending-dealing procedure is invoked after current xml mapper is parsed, but its logic is WRONG! Consider this xml mapper dependency graph A<–B<–C, apparently you should do
parsePendingXXX
in recursive fashion when parsing C, or you have a chance to get A left incomplete! And then aforementioned exception is raised whenbuildAllStatements
hit twice.It should be fixed in the latest 3.5.0-SNAPSHOT. If there still is a similar problem (it’s possible), please create a test case (see the ones I created).
@lythesia , Thanks again for the repro!