property tag in include tag cannot override parameters of foreach

24 views
Skip to first unread message

Jerry yuan

unread,
Jun 11, 2023, 11:37:54 PM6/11/23
to mybatis-user
I'm using mybatis-generator to generate the base framework of mappers and I have DemoMapper.xml generated by mybatis-generator:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="y2023.m06.mapper.DemoMapper" >
<resultMap id="BaseResultMap" type="y2023.m06.domain.Demo" >
...
</resultMap>
<sql id="Example_Where_Clause" >
<where >
<foreach collection="oredCriteria" item="criteria" separator="or" >
...
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause" >
...
</sql>
<sql id="Base_Column_List" >
...
</sql>
</mapper>


For the reason that I want to extend the mapper with out modifing generated files, I created an other mapper named DemoMapperExt with DemoMapperExt.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="y2023.m06.mapper.DemoMapperExt">
<resultMap id="BaseCountGroupMap" type="y2023.m06.domain.DemoCountGroup"
extends="y2023.m06.mapper.CmAuditJobMapper.BaseResultMap">
<result column="cnt" jdbcType="BIGINT" property="cnt" javaType="java.lang.Long"/>
</resultMap>
<select id="countGroupByExample" resultMap="BaseCountGroupMap">
<include refid="y2023.m06.mapper.CmAuditJobMapper.Example_Where_Clause">
<property name="oredCriteria" value="example.oredCriteria"/>
</include>
</select>
</mapper>

While when I invoking DemoMapperExt.countGroupByExample, I got an exception:

Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'oredCriteria' not found. Available parameters are [groupColumns, param1, example, param2]
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'oredCriteria' not found. Available parameters are [groupColumns, param1, example, param2]
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:156)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:142)
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:147)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80)
at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:142)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
at com.sun.proxy.$Proxy4.countGroupByExample(Unknown Source)
at y2023.m06.ManualLoadMyBatisMapperTest.main(ManualLoadMyBatisMapperTest.java:54)
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'oredCriteria' not found. Available parameters are [groupColumns, param1, example, param2]
at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:210)
at org.apache.ibatis.scripting.xmltags.DynamicContext$ContextAccessor.getProperty(DynamicContext.java:119)
at org.apache.ibatis.ognl.OgnlRuntime.getProperty(OgnlRuntime.java:3344)
at org.apache.ibatis.ognl.ASTProperty.getValueBody(ASTProperty.java:121)
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:586)
at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:550)
at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:46)
at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateIterable(ExpressionEvaluator.java:54)
at org.apache.ibatis.scripting.xmltags.ForEachSqlNode.apply(ForEachSqlNode.java:71)
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.lambda$apply$0(MixedSqlNode.java:32)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:32)
at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:58)
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.lambda$apply$0(MixedSqlNode.java:32)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:32)
at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:39)
at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:320)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:88)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:154)
... 8 more

It sad there has no parameters named "oredCriteria", which already overrided by property tag with "example.oredCriteria".

I tried to debug into mybatis and found it will process includes when loading xml files at "mybatis-3.5.13-sources.jar!/org/apache/ibatis/builder/xml/XMLIncludeTransformer.java:65":
Snipaste_2023-06-12_10-30-24.png
In this line, toIncludeContext has been set to property list's variable mapping:
Snipaste_2023-06-12_10-36-05.png
Continue to step in and stop at it processing the foreach tag:
Snipaste_2023-06-12_10-35-46.png
It tried to replace attribute with properties map at "mybatis-3.5.13-sources.jar!/org/apache/ibatis/builder/xml/XMLIncludeTransformer.java:80"
Snipaste_2023-06-12_10-40-35.png
but PropertyParse.parse will only replace those references with "${" prefix and "}" suffix:
Snipaste_2023-06-12_10-42-32.png
Snipaste_2023-06-12_10-51-17.png
After this, mybatis will still try to find oredCriteria in root Context and lead to a fail.
Snipaste_2023-06-12_10-55-01.png
Reply all
Reply to author
Forward
0 new messages