2

Is it possible in myBatis 3 to map a single result to multiple objects, ensuring that the objects all reference the same instance? Is there an example of this I could reference?

Updated to add more detail:

For instance, let's say I store information regarding Contacts for my application in my DB. I want to know if it's possible to use myBatis to map the same instance of a contact to, say, a Listing class, which holds a Contact:

public class Listing {
    private Contact myContact;
    //getters & setters...
}

as well as to a ContactsHolder class, which also holds a Contact:

public class ContactsHolder {
    private Contact aContact
    //getters & setters...
}

I need the object that is mapped by myBatis to both the Listing and ContactsHolder classes to be the same instance. Is this possible?

holic87
  • 791
  • 2
  • 17
  • 29
  • Can you give more information on the problem your trying to solve? The result mapping in MyBatis 3 is extremely powerful, it does a lot. – Andy Oct 26 '11 at 18:38
  • @AndyPryor: I have updated my question for more detail as to the problem I'm trying to solve. I hope this helps clarify what I'm trying to do. Thanks! – holic87 Oct 26 '11 at 18:53
  • Are you trying to get an instance of "Listing" and and instance of "ContactsHolder" is one database call? – Andy Oct 26 '11 at 19:30
  • @AndyPryor: Yes, though it doesn't have to be in one database call necessarily. As long as the instance of the `Contact` that is mapped in both classes is the same, that's I all need. – holic87 Oct 26 '11 at 20:40

2 Answers2

1

No, MyBatis isn't able to do that with standard result mapping. (at least to my knowledge). You could select the "Contact" object, then build a Listing and ContactsHolder manually with both of them referencing the Contact.

Or implement a custom ResultSetHandler.

It's kind of a peculiar request, I'm not sure why you want the same instances shared across two objects like that. That's probably why no feature like this exists in MyBatis 3.

Andy
  • 8,841
  • 8
  • 45
  • 68
  • BTW, I was able to solve this using a myBatis plugin (pg. 17 of the [User Guide](http://code.google.com/p/mybatis/downloads/detail?name=MyBatis-3-User-Guide.pdf&can=3&q=Docs)) and intercepting the `handleResultSets` method in the `ResultSetHandler` class. I was able to add the same `Contact` instance contained in the result set to both my `Listing` and `ContactsHolder` classes. – holic87 Oct 27 '11 at 23:37
0

This can be done with standard result mapping if you use select to fetch the associated contact and both objects are fetched in the same session.

Modify result maps for Listing and ContactsHolder:

<resultMap type="Listing" id="listingMap">
   <association property="myContact" column="contact_id" javaType="Contact" select="selectContact"/>
</resultMap>

<resultMap type="ContactsHolder" id="contactsHolderMap">
   <association property="aContact" column="contact_id" javaType="Contact" select="selectContact"/>
</resultMap>

Now create a query selectContact:

<select id='selectContact' resultType='Contact'>
     SELECT * from contact where id = #{id}
</select>

Now if you create some select that uses both listingMap and contactsHolderMap to map Listing and ContactsHolder records that reference the same contact they will both query for the contact using the same id.

Mybatis uses local cache for all objects read in a session so during fetching of the second associated contact the cache will be hit and the same object will be reused.

Even if you do two queries manually to get Listing and ContactsHolder in the same transaction the same Contact will be used in both returned objects.