|
I'm using a select query with a left join in conjunction with a result
map of the following form: <resultMap id="..." type="ContainingObject"> ... <collection property="..." ofType="InnerObject"> ... </collection> </resultMap> class InnerObject { private ContainingObject parent; ... } It's working well, but I haven't figured out a way to populate the parent property of the InnerObject instances using a result map. Is that possible or should I just loop over the InnerObjects and assign the reference to the parent object? Thanks, Matt |
|
MyBatis will not do that directly.
What you need to do is implement a ResultHandler that will do this. ResultHandler is a very simple interface so it should be easy for you. Note that the ResultHandler's method will be called once for each row so you may want to keep a reference to the parent obtained in the first row so that all inner objects refer to the same parent. Christian -----Message d'origine----- De : [hidden email] [mailto:[hidden email]] De la part de Matt Passell Envoyé : September-02-10 7:48 PM À : mybatis-user Objet : Reference to containing object for objects in a collection I'm using a select query with a left join in conjunction with a result map of the following form: <resultMap id="..." type="ContainingObject"> ... <collection property="..." ofType="InnerObject"> ... </collection> </resultMap> class InnerObject { private ContainingObject parent; ... } It's working well, but I haven't figured out a way to populate the parent property of the InnerObject instances using a result map. Is that possible or should I just loop over the InnerObjects and assign the reference to the parent object? Thanks, Matt |
|
Hi Christian,
Thanks for the response. I'll try implementing my own ResultHandler. The user guide doesn't say much about ResultHandlers. Do you know of any example code I could look at? Also, I'm currently using mapper interfaces where possible. The main way I can see to use a ResultHandler is through the SqlSession.select() methods. Is there any way to combine a ResultHandler and a mapper interface?
Thanks, Matt
On Fri, Sep 3, 2010 at 7:26 AM, Poitras Christian <[hidden email]> wrote: MyBatis will not do that directly. |
|
Pretty simple, this is your result handler:
// Import iBatis stuff import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.ResultContext; public class ResultHandlerImpl implements ResultHandler { public void handleResult (ResultContext resultContext) { // Get the result object, the object returned by the select() final Object object = resultContext.getResultObject(); } } And this is how you pass it: // Select with result handler sqlSession.select(sqlMapName, null, resultHandlerImpl); François On Sep 3, 2010, at 10:54 AM, Matt Passell wrote: > Hi Christian, > > Thanks for the response. I'll try implementing my own ResultHandler. The user guide doesn't say much about ResultHandlers. Do you know of any example code I could look at? Also, I'm currently using mapper interfaces where possible. The main way I can see to use a ResultHandler is through the SqlSession.select() methods. Is there any way to combine a ResultHandler and a mapper interface? > > Thanks, > Matt > > > On Fri, Sep 3, 2010 at 7:26 AM, Poitras Christian <[hidden email]> wrote: > MyBatis will not do that directly. > What you need to do is implement a ResultHandler that will do this. ResultHandler is a very simple interface so it should be easy for you. > Note that the ResultHandler's method will be called once for each row so you may want to keep a reference to the parent obtained in the first row so that all inner objects refer to the same parent. > > Christian > > -----Message d'origine----- > De : [hidden email] [mailto:[hidden email]] De la part de Matt Passell > Envoyé : September-02-10 7:48 PM > À : mybatis-user > Objet : Reference to containing object for objects in a collection > > I'm using a select query with a left join in conjunction with a result > map of the following form: > > <resultMap id="..." type="ContainingObject"> > ... > <collection property="..." ofType="InnerObject"> > ... > </collection> > </resultMap> > > class InnerObject { > private ContainingObject parent; > ... > } > > It's working well, but I haven't figured out a way to populate the > parent property of the InnerObject instances using a result map. Is > that possible or should I just loop over the InnerObjects and assign > the reference to the parent object? > > Thanks, > Matt |
|
Thanks François!
MyBatis site is missing an example of a ResultHandler. It would be nice to add one! To answer the question between mapper and ResultHandler, there is no easy way to link both right now. As you mentioned the only way to use a ResultHandler is trough the SqlSession.select() method. Fortunately, MyBatis will still use the ResultMap to convert the row into some business domain object(s). But for this to work, you must use XML... If you like, we would be very interested to have a plugin to allow to call a mapper's method with a ResultHandler. We may even add it to MyBatis's core too. Christian -----Message d'origine----- De : [hidden email] [mailto:[hidden email]] De la part de François Schiettecatte Envoyé : September-03-10 11:03 AM À : [hidden email] Objet : Re: Reference to containing object for objects in a collection Pretty simple, this is your result handler: // Import iBatis stuff import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.ResultContext; public class ResultHandlerImpl implements ResultHandler { public void handleResult (ResultContext resultContext) { // Get the result object, the object returned by the select() final Object object = resultContext.getResultObject(); } } And this is how you pass it: // Select with result handler sqlSession.select(sqlMapName, null, resultHandlerImpl); François On Sep 3, 2010, at 10:54 AM, Matt Passell wrote: > Hi Christian, > > Thanks for the response. I'll try implementing my own ResultHandler. The user guide doesn't say much about ResultHandlers. Do you know of any example code I could look at? Also, I'm currently using mapper interfaces where possible. The main way I can see to use a ResultHandler is through the SqlSession.select() methods. Is there any way to combine a ResultHandler and a mapper interface? > > Thanks, > Matt > > > On Fri, Sep 3, 2010 at 7:26 AM, Poitras Christian <[hidden email]> wrote: > MyBatis will not do that directly. > What you need to do is implement a ResultHandler that will do this. ResultHandler is a very simple interface so it should be easy for you. > Note that the ResultHandler's method will be called once for each row so you may want to keep a reference to the parent obtained in the first row so that all inner objects refer to the same parent. > > Christian > > -----Message d'origine----- > De : [hidden email] [mailto:[hidden email]] De la part de Matt Passell > Envoyé : September-02-10 7:48 PM > À : mybatis-user > Objet : Reference to containing object for objects in a collection > > I'm using a select query with a left join in conjunction with a result > map of the following form: > > <resultMap id="..." type="ContainingObject"> > ... > <collection property="..." ofType="InnerObject"> > ... > </collection> > </resultMap> > > class InnerObject { > private ContainingObject parent; > ... > } > > It's working well, but I haven't figured out a way to populate the > parent property of the InnerObject instances using a result map. Is > that possible or should I just loop over the InnerObjects and assign > the reference to the parent object? > > Thanks, > Matt |
|
Thanks François and Christian. I gave it a try with my own ResultHandler and with DefaultResultHandler and I was surprised to see (in the debugger) that handleResult() was only being called once even though the ResultSet contains 2 rows. Is that what you'd expect? If I'm doing something wrong, any idea what it might be? I'm executing code very similar to François's example and the select statement defined in the XML mapping involves a simple left join similar to the following (where table a is used to build the ContainingObjects and table b is used to build the InnerObjects):
from a left join b on a.id = b.foreign_key As I get to know the MyBatis code better, I'll see if I can figure out a good way to add the ability to call a mapper's method with a ResultHandler. All of the method declarations in my mapper interfaces (and those in the user guide) take at most one parameter. Do you think the most practical way to add this functionality would be to also recognize methods including a ResultHander? I'm guessing you guys use dynamic proxies to provide an implementation for a mapper interface. Is that right?
Thanks, Matt On Fri, Sep 3, 2010 at 11:17 AM, Poitras Christian <[hidden email]> wrote: Thanks François! |
|
I may have been wrong. I haven’t used any ResultHandler
with a <collection>. The ResultHandler might be called once for each “result”
found. In this case “result” means one object matching the
resultMap. So in your case, it might be one outer object containing 2 inner
object. If your select returns 2 outer objects, than I am confused about
the ResultHandler being called once... Unless you called stop() inside the ResultHandler. Mapper are proxies. I guess it would be possible to check if a
parameter is a ResultHandler and in such a case, use it. The complex part is
that the parameter must be ignored when matching mapper methods to XML. Christian De : [hidden email]
[mailto:[hidden email]] De la part de Matt Passell Thanks François and Christian. I gave it a try
with my own ResultHandler and with DefaultResultHandler and I was surprised to
see (in the debugger) that handleResult() was only being called once even
though the ResultSet contains 2 rows. Is that what you'd expect? If
I'm doing something wrong, any idea what it might be? I'm executing code
very similar to François's example and the select statement defined in the
XML mapping involves a simple left join similar to the following (where table a
is used to build the ContainingObjects and table b is used to build the
InnerObjects): from a left join b on a.id
= b.foreign_key As I get to know the MyBatis code better, I'll see if I can
figure out a good way to add the ability to call a mapper's method with a
ResultHandler. All of the method declarations in my mapper interfaces
(and those in the user guide) take at most one parameter. Do you think
the most practical way to add this functionality would be to also recognize
methods including a ResultHander? I'm guessing you guys use dynamic
proxies to provide an implementation for a mapper interface. Is that
right? Thanks, Matt On Fri, Sep 3, 2010 at 11:17 AM, Poitras Christian <[hidden email]>
wrote: Thanks François!
|
|
Yup, that's it. The ResultSet contains two rows with data like this:
<columns for outer1> <columns for inner1> <columns for outer1> <columns for inner2> The ResultHandler is called once for the single outer result when the first row is handled (at that point the outer object only contains one inner object). When the second row is handled, since it is associated with the same outer result, it builds the inner object and adds it to the collection property without calling the ResultHandler a second time. Given that's how it works, maybe I should fall back on the approach of iterating over the inner objects and setting their reference to the outer object after each outer object is fully realized.
I'll let you know if I do anything more with the ResultHandler/Mapper interface combination. Thanks, Matt
On Fri, Sep 3, 2010 at 1:18 PM, Poitras Christian <[hidden email]> wrote:
|
|
In reply to this post by Poitras Christian
Christian
You should feel free to add this example to the site, I could clean this up into a real example of you want. Cheers François On Sep 3, 2010, at 11:17 AM, Poitras Christian wrote: > Thanks François! > MyBatis site is missing an example of a ResultHandler. It would be nice to add one! > > To answer the question between mapper and ResultHandler, there is no easy way to link both right now. As you mentioned the only way to use a ResultHandler is trough the SqlSession.select() method. > Fortunately, MyBatis will still use the ResultMap to convert the row into some business domain object(s). But for this to work, you must use XML... > > If you like, we would be very interested to have a plugin to allow to call a mapper's method with a ResultHandler. We may even add it to MyBatis's core too. > > Christian > > -----Message d'origine----- > De : [hidden email] [mailto:[hidden email]] De la part de François Schiettecatte > Envoyé : September-03-10 11:03 AM > À : [hidden email] > Objet : Re: Reference to containing object for objects in a collection > > Pretty simple, this is your result handler: > > // Import iBatis stuff > import org.apache.ibatis.session.ResultHandler; > import org.apache.ibatis.session.ResultContext; > > public class ResultHandlerImpl implements ResultHandler { > > public void handleResult (ResultContext resultContext) { > > // Get the result object, the object returned by the select() > final Object object = resultContext.getResultObject(); > > } > } > > > And this is how you pass it: > > // Select with result handler > sqlSession.select(sqlMapName, null, resultHandlerImpl); > > > François > > On Sep 3, 2010, at 10:54 AM, Matt Passell wrote: > >> Hi Christian, >> >> Thanks for the response. I'll try implementing my own ResultHandler. The user guide doesn't say much about ResultHandlers. Do you know of any example code I could look at? Also, I'm currently using mapper interfaces where possible. The main way I can see to use a ResultHandler is through the SqlSession.select() methods. Is there any way to combine a ResultHandler and a mapper interface? >> >> Thanks, >> Matt >> >> >> On Fri, Sep 3, 2010 at 7:26 AM, Poitras Christian <[hidden email]> wrote: >> MyBatis will not do that directly. >> What you need to do is implement a ResultHandler that will do this. ResultHandler is a very simple interface so it should be easy for you. >> Note that the ResultHandler's method will be called once for each row so you may want to keep a reference to the parent obtained in the first row so that all inner objects refer to the same parent. >> >> Christian >> >> -----Message d'origine----- >> De : [hidden email] [mailto:[hidden email]] De la part de Matt Passell >> Envoyé : September-02-10 7:48 PM >> À : mybatis-user >> Objet : Reference to containing object for objects in a collection >> >> I'm using a select query with a left join in conjunction with a result >> map of the following form: >> >> <resultMap id="..." type="ContainingObject"> >> ... >> <collection property="..." ofType="InnerObject"> >> ... >> </collection> >> </resultMap> >> >> class InnerObject { >> private ContainingObject parent; >> ... >> } >> >> It's working well, but I haven't figured out a way to populate the >> parent property of the InnerObject instances using a result map. Is >> that possible or should I just loop over the InnerObjects and assign >> the reference to the parent object? >> >> Thanks, >> Matt > |
|
In reply to this post by Matt Passell
On 9/2/2010 7:48 PM, Matt Passell wrote:
> It's working well, but I haven't figured out a way to populate the > parent property of the InnerObject instances using a result map. Is > that possible or should I just loop over the InnerObjects and assign > the reference to the parent object? Interesting issue. I can see where having a general capability to include a parent pointer would be handy. And since containment is pretty much the only concept that MyBatis includes, we don't have to worry about getting carried away with relationships. Since MyBatis has a reference to the parent object while it is building the children (either association or collection), having some special register like @parent would seem to be straightforward (says me without actually doing the work :). -- Guy Rouillier |
| Powered by Nabble | Edit this page |
