I wanted to pass my experience along with regard to dealing with a join based collection in MyBatis 3. I have been able to get it working. But, it took some experimentation to figure out what I needed to do. I think the docs may need to be improved around this. But, I wanted to confirm that what I am experiencing is expected.
I'll chronicle my path of discovery using the SQL examples from the mybatis docs as a basis.
I used a select statement and an initial resultmap like the following:
<select id="selectBlog" parameterType="int" resultMap="blogResult">
select
B.id,
B.title,
B.author_id as authorId,
P.id as post_id,
P.subject as post_subject,
P.body as post_body,
from Blog B
left outer join Post P on B.id = P.blog_id
where B.id = #{id}
</select>
<resultMap id="blogResult" type="Blog">
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
</resultMap>My resultmap was defined as minimalistic as I thought I could get away with. Notice that I did not define an "id" in the resultMap. I simply defined the collection. Inefficiencies aside I thought mybatis would recognize the non-collection columns were identical and create the collections items accordingly I'm not saying this was a good assumption. It was just where my mind was and nothing that _I saw_ (i know it is there) in the documentation was telling me that I needed to have the id column defined in order for the collections to work properly.
The result of this was that I had a Blog object with none of the fields populated except for the posts. But each empty Blog had only one Post in each of their posts collection.
<resultMap id="blogResult" type="Blog">
<id property="id" column="id" />
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
</resultMap>
Next, I decided to try out adding the id column (duh). This provided me the results that I expected with regard to my collection of posts in each Blog being populated properly. But, my Blog was still empty on everything except the id and the posts.
This struck me as odd because the autoMappingBehavior is documented as being set to PARTIAL. The docs define it in the following way:
Specifies if and how MyBatis should automatically map columns to fields/properties. NONE disables auto-mapping. PARTIAL will only auto-map results with no nested result mappings defined inside. FULL will auto-map result mappings of any complexity (containing nested or otherwise).
PARTIAL will only auto-map results with no nested result mappings defined inside.
Given that I did not have a nested result mapping in my resultmap (unless a collection is considered a nested result map) i thought it would map my Blog results properly without any modification. This was clearly not the case.
I thought perhaps I was going to have to define my full resultMap which would have been a bummer since the actual work i was doing was significantly more than the Blog/Post example.
I noticed that the resultMap had an attribute to set the autoMapping. I read the documentation on this and it states the following:
| autoMapping |
If present, MyBatis will enable or disable the automapping for this ResultMap. This attribute overrides the global autoMappingBehavior. Default: unset. |
This attribute overrides the global autoMappingBehavior.
I assumed this meant that I needed to set the value to NONE, PARTIAL, or FULL. But, in reality this is a boolean setting of true/false.
<resultMap id="blogResult" type="Blog" autoMapping="true">
<id property="id" column="id" />
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
</resultMap>I finally achieved the expected result I wanted. The Blog properties were properly populated and the collection of Posts were properly populated. If my final result is what is expected, then I think the documentation may need to make a few things more clear.
1) It may be good to emphasize the portion of the documentation that states:
"Again, remember the importance of the id elements here, or read the association section above if you haven't already."
2) I think it may be wise to update the autoMapping docs to provide what the possible values are and state that "unset"(default behavior) will not auto map undefined columns in the resultMap.
| autoMapping |
If present, MyBatis will enable (true) or disable (false) the automapping for this ResultMap. This attribute overrides the global autoMappingBehavior. Default: unset (same as false). |
Thoughts? Insights?