-
Notifications
You must be signed in to change notification settings - Fork 13k

Description
MyBatis version
3.2.5+
Database vendor and version
Oracle 12c
Test case or example project
@Result(
property="someProperty",
column="{param1Name=resultColumnNameForParam1, param2Name=resultColumnNameForParam2}",
one=@One(select = "foo.MapperClass.mapperMethodName"))
@Select("select * from someTable where column1 = #{param1Name,jdbcType=INTEGER} and column2 = #{param2Name,jdbcType=INTEGER}")
int mapperMethodName(@Param("param1Name") int param1Name, @Param("param2Name") int param2Name)
Steps to reproduce
- Have a nested query that uses a mapper method taking multiple parameters.
- Use a composite key for column like:
- "{param1Name=resultColumnNameForParam1, param2Name=resultColumnNameForParam2}"
- or "param1Name=resultColumnNameForParam1, param2Name=resultColumnNameForParam2"
Expected result
Nested query with composite key works successfully.
Actual result
BindException is thrown "org.apache.ibatis.binding.BindingException: Parameter 'param1Name' not found. Available parameters are []"
Cause
This appears to have been caused by the fix for issue #135.
It makes the following change:
parameterType = ParamMap.class; // issue #135
whereas before that was:
parameterType = Map.class;
Map does not throw an error on retrieving a key that doesn't exist, while ParamMap does throw a BindException in this scenario.
This causes DefaultResultSetHandler to fail when it makes a call to prepareCompositeKeyParameter(). It constructs a MetaObject wrapping a ParamMap when it used to wrap a Map. This results in a MapWrapper being created by the MetaObject.
When prepareCompositeKeyParameter then makes a call to MetaObject.getSetterType() which calls MapWrapper.getSetterType(), the BindException is thrown.
In MapWrapper you can see the following code in getSetterType:
if (map.get(name) != null) {
return map.get(name).getClass();
} else {
return Object.class;
}
The else can never be reached for a ParamMap because it will never return null, but instead throw a BindException.