MyBatis: Controlling Object Creation vs. Referencing Existing Objects

血红的双手。 提交于 2020-07-22 05:20:32

问题


This is my first question here, so please let me know if there's anything I can provide to make my question clearer. Thanks!

Is there anyway to tweak MyBatis (3.0.4) so that when it's running through the nested result maps and creating objects based on the results, it doesn't create "duplicate" objects and instead references the object that has already been created? To clarify, let's say I've got an object that consists of the following (simplified) info:

Public class PrimaryObject {
    Private Contact role1;
    Private Contact role2;
    Private List<OtherObject> otherObjects;
}  

Public class OtherObject {
    Private String otherProperty;
    Private Contact otherRole;
}

And the result maps/SQL (assume type aliases):

<mapper namespace="PrimaryObject">
    <resultMap id="primaryObject" type="primaryObject">
        <association property="role1" column="ROLE_1_ID"
         select="Contact.findContactByPK" />
        <association property="role2" column="ROLE_2_ID"
         select="Contact.findContactByPK" />
        <collection property="otherObjects" column="PRIMARY_OBJECT_ID"
         javaType="List" ofType="OtherObject"
         select="OtherObject.findOtherObjectsByPrimaryObjectPK" />
    </resultMap>
    <select id="selectPrimaryObjectByPK" parameterType="..."
     resultMap="primaryObject">
        SELECT * FROM PRIMARY_OBJECT_TABLE
        WHERE PRIMARY_OBJECT_ID = #{value}
    </select>

...

<mapper namespace="OtherObject">
    <resultMap id="otherObject" type="otherObject">
        <result property="otherProperty" column="OTHER_PROPERTY" />
        <association property="otherRole" column="OTHER_ROLE_ID"
         select="Contact.findContactByPK" />
    </resultMap>
    <select id="findOtherObjectsByPrimaryObjectPK" parameterType="..."
     resultMap="otherObject">
        SELECT OTHER_OBJECT.OTHER_PROPERTY, OTHER_OBJECT.OTHER_ROLE_ID
        FROM OTHER_OBJECT JOIN PRIMARY_OBJECT
            ON PRIMARY_OBJECT.PRIMARY_OBJECT_ID = OTHER_OBJECT.PRIMARY_OBJECT_ID
    </select>

...

<mapper namespace="Contact">
    <resultMap id="contact" type="Contact">
        <result property...
        ...
    </resultMap>
    <select id="findContactByPK" parameterType="..." resultMap="contact">
        SELECT * FROM CONTACT...
    </select>

Now let's say a contact is acting as both role1 and role2 on primaryObject. From what I've seen, MyBatis creates the contact object referenced in role1, and when it hits role2, it simply references the object it created for role1. That's great!

However, let's say that same contact is acting as the otherRole in otherObject. MyBatis now creates an identical contact object, as opposed to just referencing the original contact created/referenced when making the primaryObject. Is there any way I can prevent this from happening, and instead just store a reference in my otherObject that references that same contact that the two different fields in primaryObject are pointing to? I've been looking at a custom ResultHandler, but the example's complexity coupled with my lack of experience is preventing me from understanding if it even addresses the problem I'm trying to solve in the first place. Thanks in advance for your help and patience!


回答1:


OK, I think your question might be a duplicate of How to map a myBatis result to multiple objects?. So, no MyBatis does not have native support for this problem, if I'm understanding it correctly.

You should be careful using nested selects, as they execute addition select statements on the database. I suggest checking out the MyBatis 3 User Guide, particularly around page 35 and up. MyBatis has very powerful ways to avoid the n+1 selects problem. What is SELECT N+1?



来源:https://stackoverflow.com/questions/8013674/mybatis-controlling-object-creation-vs-referencing-existing-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!