mybatis-3
mybatis-3 copied to clipboard
Constructor Args Map Incorrect Columns When Using resultMap property
MyBatis version
3.4.4 tested with 3.4.2, 3.4.0 as well.
Database vendor and version
H2 version 1.4.193 (although this issue is not related to H2 per se)
Test case or example project
Please see self-contained maven project with the full regression test (5.8KB) regression0.zip
Steps to reproduce
Create a constructor result map <arg/>
or <idArg/>
that references another POJO that has similarly named property to the one being mapped. See below (or attached regression test for full mapping):
<resultMap id="ParentResultMap" type="dto.Parent">
<constructor>
<!-- this property is named 'id' in the Parent class -->
<arg column="p_id" javaType="java.lang.String" jdbcType="VARCHAR"/>
<!-- ... more ... -->
</constructor>
</resultMap>
<resultMap id="ChildResultMap" type="dto.Child">
<constructor>
<!-- this property is named 'id' in the Child class -->
<idArg column="id" javaType="java.lang.String" jdbcType="VARCHAR"/>
<!-- ... more ...-->
<arg javaType="dto.Parent" resultMap="ParentResultMap"/>
</constructor>
</resultMap>
public class Parent {
private final String id;
// ...
public Parent(String id /*, ...*/) {
this.id = id;
//....
}
//...
}
public class Child {
private final String id;
//...
private final Parent parent;
public Child(String id, /*, ... */ Parent parent) {
this.id = id;
//...
this.parent = parent;
}
//...
}
Expected result
Column p_id
should map to Parent
's constructor first argument. For the row returned below
ID, NAME, P_ID, P_NAME
10, Child Name, 11, Parent Name
Parent
's id
should be 11
Actual result
Column id
is instead mapped to the Parent
's constructor first argument. For the row shown above, Parent
's id
is instead 10
Workarounds
- Rename properties so that names don't match between classes, or
- Convert immutable classes to mutable with default constructor, getters and setters, then switch mapping to non-constructor mapping using
<result/>
.
This has to do with how mybatis allows both constructor mapping and post constructor setter mapping Which is useful for example for collections which constructor mapping does not currently support unless you use a sub select.
I'm trying to see how to 'disable' this behavior without breaking the post constructor property setting but for now you can also set the automappingbehavior (assuming that doesn't break other parts of your app)
configuration.setAutoMappingBehavior(AutoMappingBehavior.NONE);
Another workaround is autoMapping="false"
on resultMap
element as follow:
<resultMap id="ParentResultMap" type="dto.Parent" autoMapping="false">
<!-- ... -->
</resultMap>
Ah yea thanks for the reminder @kazuki43zoo
automapping doesn't exist on the annotations yet. The solution propose by @kazuki43zoo only works for xml mapping or globally atm.