It should be possible to declare result handlers during configuration.

classic Classic list List threaded Threaded
7 messages Options
q8p
Reply | Threaded
Open this post in threaded view
|

It should be possible to declare result handlers during configuration.

q8p
(this modified repost of "ResultHandler specification in mapper
configuration" has been requested in issue 312 to discuss further
here)

We are using MyBatis, with spring integration and lazy loading. Now we
are running into a limitation in MyBatis: It is not possible to --
configure -- a mapper with a result handler. The current approach to
relate a result handler at runtime (with a mapped statement is to pass
it as an argument to a SqlSession) spoils all the magic when using
spring and/or (lazy loaded) collections.

Spoiling spring:
Spring integration provides a way to automatically register mappers in
the spring context. Users of a mapper can call mapped statements,
except when a 'special' result handler is needed; then the caller or
the method needs to know which result handler to use.

Spoiling (lazy loaded) collections:
(Lazy loaded) collection provides a way chain mappers. The big
advantage is that mappers can be easily reused when there is a join
relation, except when a 'special' result handler is needed to process
the results from the 'collection' mapper; the magic is gone, because
the special mapper that is needed to do some special processing is not
used when loading the collection data (there is no way to do that,
because the chain is specified -- configuration time --, and not
runtime.

Discussion topic: It should be possible to declare result handlers
during configuration.

Why? I most cases where you want a specific handler (eg. to relate
parents and childs as in http://code.google.com/p/mybatis/wiki/ResultHandlerExample),
you always what to use that handler. A specification in the mapper XML
(or annotation) prevents users of that mapper to forget to use the
right handler.

What's next? I've posted a patch (in issue 312) that implements:
- A 'resultHandlerType' to the resultMap configuration which is used
when no specific result handler is passed at runtime
- The 'resultHandlerType' of the mapper referred to in a 'collection'
which is to build the result collection.
- A MyBatis defaultResultHandlerType to configure the default handler
type (and use DefaultResultHandler when it is not specified). This
allows users to use a different type if List as a default. We use this
feature, because we always want a special kind of List to put the
results in.

Let's discuss!
Reply | Threaded
Open this post in threaded view
|

Re: It should be possible to declare result handlers during configuration.

Eduardo Macarron
I see the point.

The main purpose is to be able to provide a custom result handler that
will create complex object graphs that out of the box result handling
cannot provide.

+1 to this change.
Reply | Threaded
Open this post in threaded view
|

Re: It should be possible to declare result handlers during configuration.

Eduardo Macarron

Let me center the objective of this change to let other devs discuss
it.

Spoiling spring: The magic with DI is that mappers are injected into
your beans, so you can not use SqlSession at all. This did not work if
a ResultHandler was needed but that was fixed in issue #322. Now
mappers can get a ResultHandler so I would say that this problem no
longer exists.

Spoiling (lazy loaded) collections: You are right here at this point.
A mapper that needs a specific ResultHandler cannot be reused. But
should it be?

The question is: what is a ResultHandler for? A ResultHandler just
gives the results row by row instead of returning them inside a list.
Mapping has already been applied and result objects are already
created, populated and passed to the ResultHandler.

ResultHandler could be useful to perform transformations for each
object but for that purpose you will need some "context", lets say,
some external data. If the ResultHandler is created by configuration,
there will be no way to pass that context so it must work just with
data contained in the result.

So I suppose that adding a ResultHandler by configuration will just
let you transform your objects using just the info held in them. For
example, MyBatis gives you an object X and you split it in a more
complex structure. But why not using a result map for that?
q8p
Reply | Threaded
Open this post in threaded view
|

Re: It should be possible to declare result handlers during configuration.

q8p
For our project (which uses spring integration with lazy-loading)
there are two purposes: 1. Handling object graphs and 2. Controlling
which 'List' implementation is used. For both purposes a
'configuration time' ResultHandler specification will be sufficient,
because the ResultHandler does not need to know anything from the
outside world.

Spoiling spring:
The solution of issue #322 does allow the caller of a mapper method to
specify the resultHandler to use, but I would like to hide that. When
handling object graphs most of the times a 'mapper specific' result
handler is needed that knows how to relate records / java objects. The
nice thing of spring integration is that the caller just calls
'get...' and the results are there; no further knowledge of which
'mapper specific' resulthandler is needed.

Spoiling (lazy loaded) collections:
We would like to use collections, but currently it's not possible to
have a mapper with a collection of interrelated objects (ie. a complex
object graph).

But why not using a result map for that? I agree with your point, but
we do not use the ResultHandler to transform or split the created
object into something else; we need it to relate objects within the
result and to control the type of List that is used.

I can imaging that you think: 'Why do you need a special kind of
List?': We use a special kind of List that also has 'indexing'
functionality (a kind of map). This allows us to fetch a specific
object from the list by referring to the indexed item (most of the
times the 'id'). When we cannot control the type of List that is used,
then we would not be able to use 'collections' (and our code would be
very inefficient, because we need to transform all List created by
ResultHandlers into our own List implementation).

One final note about passing 'context' to a ResultHandler that is
configured in a mapper: When a ResultHandler would have access to the
Mapper arguments, then it would be possible to pass a context object
as one of the mapper parameters. In that case you would have the best
of both worlds: The developer does not need to know which
ResultHandler to use and the mapper method just has a context
argument. Maybe better to discuss this in another topic?


On 24 jun, 11:41, Eduardo <[hidden email]> wrote:

> Let me center the objective of this change to let other devs discuss
> it.
>
> Spoiling spring: The magic with DI is that mappers are injected into
> your beans, so you can not use SqlSession at all. This did not work if
> a ResultHandler was needed but that was fixed in issue #322. Now
> mappers can get a ResultHandler so I would say that this problem no
> longer exists.
>
> Spoiling (lazy loaded) collections: You are right here at this point.
> A mapper that needs a specific ResultHandler cannot be reused. But
> should it be?
>
> The question is: what is a ResultHandler for? A ResultHandler just
> gives the results row by row instead of returning them inside a list.
> Mapping has already been applied and result objects are already
> created, populated and passed to the ResultHandler.
>
> ResultHandler could be useful to perform transformations for each
> object but for that purpose you will need some "context", lets say,
> some external data. If the ResultHandler is created by configuration,
> there will be no way to pass that context so it must work just with
> data contained in the result.
>
> So I suppose that adding a ResultHandler by configuration will just
> let you transform your objects using just the info held in them. For
> example, MyBatis gives you an object X and you split it in a more
> complex structure. But why not using a result map for that?
Reply | Threaded
Open this post in threaded view
|

Re: It should be possible to declare result handlers during configuration.

Clinton Begin
Administrator
 
So to summarize:

Currently ResultHandlers are passed in as method parameters at the time of the call using one of the following overloaded select methods:

void select(String statement, Object parameter, ResultHandler handler)
void select(String statement, Object parameter, RowBounds rowBounds,ResultHandler handler)

What you're suggesting is that in addition to those, a "default" ResultHandler could be identified in a mapped statement like this:

    <select id="selectBlog" parameterType="int" resultType="Blog" defaultResultHandlerType="com.me.MyResultHandler">
      select * from Blog where id = #{id}
    </select>

And then you could call two new overloads of the select method as so:

    void select(String statement, Object parameter)
    void select(String statement, Object parameter, RowBounds rowBounds)

And in which case if no defaultResultHandlerType is specified, then the MyBatis default ResultHandler would be used (essentially resulting in no useful results, given that there's no way to retrieve or return the data).

So far, that all sounds fine.  But Eduardo's point is key.  

Normally the pattern looks something like this:

    MyResultHandler mrh = new MyResultHandler();
    sqlSession.select("somestatement", aParameter, mrh);
    List subset = mrh.getListOfFilteredResultsOrderedByID();

How do you access the context (state) of the RowHandler?  Since its lifecycle is now up to MyBatis to facilitate, you will never have an opportunity to access the state.  This will result in strange patterns like using ThreadLocal Singletons to temporarily store results so that it can be retrieved in other scopes.  

Now if all the ResultHandler is meant to do is read each record, and modify it (with insert/update/delete) inside of the ResultHandler, or write it to a file, or something whereby the rest of the application never needs it, then that will work fine.  But I think such usages are fairly rare (especially considering that you wouldn't even be able to pass in the filename or any other parameters).

Of course all of this is solvable by introducing some form of named ResultHandler bean in the thread local scope, and then use that named result handler instead of a  defaultResultHandlerType (it would become resultHandlerRef or something).   However, then MyBatis enters the realm of acting like a dependency injection container.  Perhaps this fits better as a feature of MyBatis Spring or perhaps not at all?

So while I think the implementation of this would be quite simple and non-intrusive... the value of it is in question.

Therefore I can't offer my support for this feature just yet. 

Can you provide a real-world example of:

* How you'd configure the ResultHandler?
* How you'd access the context/state/results from the ResultHandler?
* How you'd use such a feature without being able to do either of the above?

Cheers,
Clinton

On Fri, Jun 24, 2011 at 1:13 PM, q8p <[hidden email]> wrote:
For our project (which uses spring integration with lazy-loading)
there are two purposes: 1. Handling object graphs and 2. Controlling
which 'List' implementation is used. For both purposes a
'configuration time' ResultHandler specification will be sufficient,
because the ResultHandler does not need to know anything from the
outside world.

Spoiling spring:
The solution of issue #322 does allow the caller of a mapper method to
specify the resultHandler to use, but I would like to hide that. When
handling object graphs most of the times a 'mapper specific' result
handler is needed that knows how to relate records / java objects. The
nice thing of spring integration is that the caller just calls
'get...' and the results are there; no further knowledge of which
'mapper specific' resulthandler is needed.

Spoiling (lazy loaded) collections:
We would like to use collections, but currently it's not possible to
have a mapper with a collection of interrelated objects (ie. a complex
object graph).

But why not using a result map for that? I agree with your point, but
we do not use the ResultHandler to transform or split the created
object into something else; we need it to relate objects within the
result and to control the type of List that is used.

I can imaging that you think: 'Why do you need a special kind of
List?': We use a special kind of List that also has 'indexing'
functionality (a kind of map). This allows us to fetch a specific
object from the list by referring to the indexed item (most of the
times the 'id'). When we cannot control the type of List that is used,
then we would not be able to use 'collections' (and our code would be
very inefficient, because we need to transform all List created by
ResultHandlers into our own List implementation).

One final note about passing 'context' to a ResultHandler that is
configured in a mapper: When a ResultHandler would have access to the
Mapper arguments, then it would be possible to pass a context object
as one of the mapper parameters. In that case you would have the best
of both worlds: The developer does not need to know which
ResultHandler to use and the mapper method just has a context
argument. Maybe better to discuss this in another topic?


On 24 jun, 11:41, Eduardo <[hidden email]> wrote:
> Let me center the objective of this change to let other devs discuss
> it.
>
> Spoiling spring: The magic with DI is that mappers are injected into
> your beans, so you can not use SqlSession at all. This did not work if
> a ResultHandler was needed but that was fixed in issue #322. Now
> mappers can get a ResultHandler so I would say that this problem no
> longer exists.
>
> Spoiling (lazy loaded) collections: You are right here at this point.
> A mapper that needs a specific ResultHandler cannot be reused. But
> should it be?
>
> The question is: what is a ResultHandler for? A ResultHandler just
> gives the results row by row instead of returning them inside a list.
> Mapping has already been applied and result objects are already
> created, populated and passed to the ResultHandler.
>
> ResultHandler could be useful to perform transformations for each
> object but for that purpose you will need some "context", lets say,
> some external data. If the ResultHandler is created by configuration,
> there will be no way to pass that context so it must work just with
> data contained in the result.
>
> So I suppose that adding a ResultHandler by configuration will just
> let you transform your objects using just the info held in them. For
> example, MyBatis gives you an object X and you split it in a more
> complex structure. But why not using a result map for that?

q8p
Reply | Threaded
Open this post in threaded view
|

Re: It should be possible to declare result handlers during configuration.

q8p
I understand your point, but my goal is a bit different. I also agree
that MyBatis should not promote using ThreadLocals to retrieve query
results

The reason for this patch is that I want to control the ResultHandler
that is used when retrieving a List: a. Using a Mapper created by
Spring or when retrieving a List attribute from a Java object that was
created by MyBatis (ie. the property was mapped with a collection
mapping). In those cases the DefaultResultHandler is being used and I
would like to control that.

Example 1: Connect objects from the query result

We have an t_employee table (with columns id, name, manager_id) and
the manager_id refers to a record from t_employee
In the Java world we have an Employee object with members 'int id,
String name, Employee manager'.

Now when querying all employees, I would like to set the employee
property. This can be done in a custom ResultHandler that does not
need to know anything from the outside world. The query result will be
a 'List' of employees that have the manager property filled.

Example 2: Use a special kind of list

We need to create a special kind of List when myBatis creates one. A
special implementation of the ResultHandler and a system wide
configuration option would allow us to do that.

To respond to your question:
 * How you'd configure the ResultHandler? In the cases above no
configuration is needed.
 * How you'd access the context/state/results from the ResultHandler?
We are using selectList, so the results are returned as a List
 * How you'd use such a feature without being able to do either of the
above? Hope the examples makes this clear.

Hope that this makes clear that there is value in 'normal' scenario's.
Happy to discuss this further. The patch i've created does provide
this functionality, so you could have a detailed look of what I mean.



The patch could be improved to also support the 'void select(...)'
scenario. Let's say we expose the parameters that were used to call
the mapper to the ResultHandler. The ResultHandler can then modify one
or more of the parameters. It will act as kind of an 'out' parameter.

The mapped statement would be the same as in your example, but the
user of the mapped statement does have a more clean interface:

List subset = new ArrayList();
sqlSession.select("somestatement", subset, mrh);

It will be even better when using the spring integration: The needed
'subset' object would be one of the Mapper method arguments: The user
of the Mapper does not need to know which ResultHandler to use and the
Java interface contract has the List as Mapper method argument.

As a real world example: you could think of a Mapper like:

class ClientDetailsMapper {
   void enrichWithClientDetails(Client aClient);
}

The mapper will select the client with aClient.id. The special
ResultHandler also has access to aClient and can enrich it with the
details. The caller of the mapper does not need to know which
ResultHandler to use.

When this adds the amount of value that is needed to get this patch
in, then i'm happy to implement it :-)

Jurriaan


On 25 jun, 16:27, Clinton Begin <[hidden email]> wrote:

> So to summarize:
>
> Currently ResultHandlers are passed in as method parameters at the time of
> the call using one of the following overloaded select methods:
>
> void select(String statement, Object parameter, ResultHandler handler)
> void select(String statement, Object parameter, RowBounds
> rowBounds,ResultHandler handler)
>
> What you're suggesting is that in addition to those, a "default"
> ResultHandler could be identified in a mapped statement like this:
>
>     <select id="selectBlog" parameterType="int" resultType="Blog"
> defaultResultHandlerType="com.me.MyResultHandler">
>       select * from Blog where id = #{id}
>     </select>
>
> And then you could call two new overloads of the select method as so:
>
>     void select(String statement, Object parameter)
>     void select(String statement, Object parameter, RowBounds rowBounds)
>
> And in which case if no defaultResultHandlerType is specified, then the
> MyBatis default ResultHandler would be used (essentially resulting in no
> useful results, given that there's no way to retrieve or return the data).
>
> So far, that all sounds fine.  But Eduardo's point is key.
>
> Normally the pattern looks something like this:
>
>     MyResultHandler mrh = new MyResultHandler();
>     sqlSession.select("somestatement", aParameter, mrh);
>     List subset = mrh.getListOfFilteredResultsOrderedByID();
>
> How do you access the context (state) of the RowHandler?  Since its
> lifecycle is now up to MyBatis to facilitate, you will never have an
> opportunity to access the state.  This will result in strange patterns like
> using ThreadLocal Singletons to temporarily store results so that it can be
> retrieved in other scopes.
>
> Now if all the ResultHandler is meant to do is read each record, and modify
> it (with insert/update/delete) inside of the ResultHandler, or write it to a
> file, or something whereby the rest of the application never needs it, then
> that will work fine.  But I think such usages are fairly rare (especially
> considering that you wouldn't even be able to pass in the filename or any
> other parameters).
>
> Of course all of this is solvable by introducing some form of named
> ResultHandler bean in the thread local scope, and then use that named result
> handler instead of a  defaultResultHandlerType (it would become
> resultHandlerRef or something).   However, then MyBatis enters the realm of
> acting like a dependency injection container.  Perhaps this fits better as a
> feature of MyBatis Spring or perhaps not at all?
>
> So while I think the implementation of this would be quite simple and
> non-intrusive... the value of it is in question.
>
> Therefore I can't offer my support for this feature just yet.
>
> Can you provide a real-world example of:
>
> * How you'd configure the ResultHandler?
> * How you'd access the context/state/results from the ResultHandler?
> * How you'd use such a feature without being able to do either of the above?
>
> Cheers,
> Clinton
>
>
>
> On Fri, Jun 24, 2011 at 1:13 PM, q8p <[hidden email]> wrote:
> > For our project (which uses spring integration with lazy-loading)
> > there are two purposes: 1. Handling object graphs and 2. Controlling
> > which 'List' implementation is used. For both purposes a
> > 'configuration time' ResultHandler specification will be sufficient,
> > because the ResultHandler does not need to know anything from the
> > outside world.
>
> > Spoiling spring:
> > The solution of issue #322 does allow the caller of a mapper method to
> > specify the resultHandler to use, but I would like to hide that. When
> > handling object graphs most of the times a 'mapper specific' result
> > handler is needed that knows how to relate records / java objects. The
> > nice thing of spring integration is that the caller just calls
> > 'get...' and the results are there; no further knowledge of which
> > 'mapper specific' resulthandler is needed.
>
> > Spoiling (lazy loaded) collections:
> > We would like to use collections, but currently it's not possible to
> > have a mapper with a collection of interrelated objects (ie. a complex
> > object graph).
>
> > But why not using a result map for that? I agree with your point, but
> > we do not use the ResultHandler to transform or split the created
> > object into something else; we need it to relate objects within the
> > result and to control the type of List that is used.
>
> > I can imaging that you think: 'Why do you need a special kind of
> > List?': We use a special kind of List that also has 'indexing'
> > functionality (a kind of map). This allows us to fetch a specific
> > object from the list by referring to the indexed item (most of the
> > times the 'id'). When we cannot control the type of List that is used,
> > then we would not be able to use 'collections' (and our code would be
> > very inefficient, because we need to transform all List created by
> > ResultHandlers into our own List implementation).
>
> > One final note about passing 'context' to a ResultHandler that is
> > configured in a mapper: When a ResultHandler would have access to the
> > Mapper arguments, then it would be possible to pass a context object
> > as one of the mapper parameters. In that case you would have the best
> > of both worlds: The developer does not need to know which
> > ResultHandler to use and the mapper method just has a context
> > argument. Maybe better to discuss this in another topic?
>
> > On 24 jun, 11:41, Eduardo <[hidden email]> wrote:
> > > Let me center the objective of this change to let other devs discuss
> > > it.
>
> > > Spoiling spring: The magic with DI is that mappers are injected into
> > > your beans, so you can not use SqlSession at all. This did not work if
> > > a ResultHandler was needed but that was fixed in issue #322. Now
> > > mappers can get a ResultHandler so I would say that this problem no
> > > longer exists.
>
> > > Spoiling (lazy loaded) collections: You are right here at this point.
> > > A mapper that needs a specific ResultHandler cannot be reused. But
> > > should it be?
>
> > > The question is: what is a ResultHandler for? A ResultHandler just
> > > gives the results row by row instead of returning them inside a list.
> > > Mapping has already been applied and result objects are already
> > > created, populated and passed to the ResultHandler.
>
> > > ResultHandler could be useful to perform transformations for each
> > > object but for that purpose you will need some "context", lets say,
> > > some external data. If the ResultHandler is created by configuration,
> > > there will be no way to pass that context so it must work just with
> > > data contained in the result.
>
> > > So I suppose that adding a ResultHandler by configuration will just
> > > let you transform your objects using just the info held in them. For
> > > example, MyBatis gives you an object X and you split it in a more
> > > complex structure. But why not using a result map for that?
q8p
Reply | Threaded
Open this post in threaded view
|

Re: It should be possible to declare result handlers during configuration.

q8p
Any other thoughts about this topic? We really need this, so i'm
trying to keep the discussion alive. When there's anything I can do to
contribute; please let me know.

Jurriaan

On 25 jun, 18:17, q8p <[hidden email]> wrote:

> I understand your point, but my goal is a bit different. I also agree
> that MyBatis should not promote using ThreadLocals to retrieve query
> results
>
> The reason for this patch is that I want to control the ResultHandler
> that is used when retrieving a List: a. Using a Mapper created by
> Spring or when retrieving a List attribute from a Java object that was
> created by MyBatis (ie. the property was mapped with a collection
> mapping). In those cases the DefaultResultHandler is being used and I
> would like to control that.
>
> Example 1: Connect objects from the query result
>
> We have an t_employee table (with columns id, name, manager_id) and
> the manager_id refers to a record from t_employee
> In the Java world we have an Employee object with members 'int id,
> String name, Employee manager'.
>
> Now when querying all employees, I would like to set the employee
> property. This can be done in a custom ResultHandler that does not
> need to know anything from the outside world. The query result will be
> a 'List' of employees that have the manager property filled.
>
> Example 2: Use a special kind of list
>
> We need to create a special kind of List when myBatis creates one. A
> special implementation of the ResultHandler and a system wide
> configuration option would allow us to do that.
>
> To respond to your question:
>  * How you'd configure the ResultHandler? In the cases above no
> configuration is needed.
>  * How you'd access the context/state/results from the ResultHandler?
> We are using selectList, so the results are returned as a List
>  * How you'd use such a feature without being able to do either of the
> above? Hope the examples makes this clear.
>
> Hope that this makes clear that there is value in 'normal' scenario's.
> Happy to discuss this further. The patch i've created does provide
> this functionality, so you could have a detailed look of what I mean.
>
> The patch could be improved to also support the 'void select(...)'
> scenario. Let's say we expose the parameters that were used to call
> the mapper to the ResultHandler. The ResultHandler can then modify one
> or more of the parameters. It will act as kind of an 'out' parameter.
>
> The mapped statement would be the same as in your example, but the
> user of the mapped statement does have a more clean interface:
>
> List subset = new ArrayList();
> sqlSession.select("somestatement", subset, mrh);
>
> It will be even better when using the spring integration: The needed
> 'subset' object would be one of the Mapper method arguments: The user
> of the Mapper does not need to know which ResultHandler to use and the
> Java interface contract has the List as Mapper method argument.
>
> As a real world example: you could think of a Mapper like:
>
> class ClientDetailsMapper {
>    void enrichWithClientDetails(Client aClient);
>
> }
>
> The mapper will select the client with aClient.id. The special
> ResultHandler also has access to aClient and can enrich it with the
> details. The caller of the mapper does not need to know which
> ResultHandler to use.
>
> When this adds the amount of value that is needed to get this patch
> in, then i'm happy to implement it :-)
>
> Jurriaan
>
> On 25 jun, 16:27, Clinton Begin <[hidden email]> wrote:
>
>
>
> > So to summarize:
>
> > Currently ResultHandlers are passed in as method parameters at the time of
> > the call using one of the following overloaded select methods:
>
> > void select(String statement, Object parameter, ResultHandler handler)
> > void select(String statement, Object parameter, RowBounds
> > rowBounds,ResultHandler handler)
>
> > What you're suggesting is that in addition to those, a "default"
> > ResultHandler could be identified in a mapped statement like this:
>
> >     <select id="selectBlog" parameterType="int" resultType="Blog"
> > defaultResultHandlerType="com.me.MyResultHandler">
> >       select * from Blog where id = #{id}
> >     </select>
>
> > And then you could call two new overloads of the select method as so:
>
> >     void select(String statement, Object parameter)
> >     void select(String statement, Object parameter, RowBounds rowBounds)
>
> > And in which case if no defaultResultHandlerType is specified, then the
> > MyBatis default ResultHandler would be used (essentially resulting in no
> > useful results, given that there's no way to retrieve or return the data).
>
> > So far, that all sounds fine.  But Eduardo's point is key.
>
> > Normally the pattern looks something like this:
>
> >     MyResultHandler mrh = new MyResultHandler();
> >     sqlSession.select("somestatement", aParameter, mrh);
> >     List subset = mrh.getListOfFilteredResultsOrderedByID();
>
> > How do you access the context (state) of the RowHandler?  Since its
> > lifecycle is now up to MyBatis to facilitate, you will never have an
> > opportunity to access the state.  This will result in strange patterns like
> > using ThreadLocal Singletons to temporarily store results so that it can be
> > retrieved in other scopes.
>
> > Now if all the ResultHandler is meant to do is read each record, and modify
> > it (with insert/update/delete) inside of the ResultHandler, or write it to a
> > file, or something whereby the rest of the application never needs it, then
> > that will work fine.  But I think such usages are fairly rare (especially
> > considering that you wouldn't even be able to pass in the filename or any
> > other parameters).
>
> > Of course all of this is solvable by introducing some form of named
> > ResultHandler bean in the thread local scope, and then use that named result
> > handler instead of a  defaultResultHandlerType (it would become
> > resultHandlerRef or something).   However, then MyBatis enters the realm of
> > acting like a dependency injection container.  Perhaps this fits better as a
> > feature of MyBatis Spring or perhaps not at all?
>
> > So while I think the implementation of this would be quite simple and
> > non-intrusive... the value of it is in question.
>
> > Therefore I can't offer my support for this feature just yet.
>
> > Can you provide a real-world example of:
>
> > * How you'd configure the ResultHandler?
> > * How you'd access the context/state/results from the ResultHandler?
> > * How you'd use such a feature without being able to do either of the above?
>
> > Cheers,
> > Clinton
>
> > On Fri, Jun 24, 2011 at 1:13 PM, q8p <[hidden email]> wrote:
> > > For our project (which uses spring integration with lazy-loading)
> > > there are two purposes: 1. Handling object graphs and 2. Controlling
> > > which 'List' implementation is used. For both purposes a
> > > 'configuration time' ResultHandler specification will be sufficient,
> > > because the ResultHandler does not need to know anything from the
> > > outside world.
>
> > > Spoiling spring:
> > > The solution of issue #322 does allow the caller of a mapper method to
> > > specify the resultHandler to use, but I would like to hide that. When
> > > handling object graphs most of the times a 'mapper specific' result
> > > handler is needed that knows how to relate records / java objects. The
> > > nice thing of spring integration is that the caller just calls
> > > 'get...' and the results are there; no further knowledge of which
> > > 'mapper specific' resulthandler is needed.
>
> > > Spoiling (lazy loaded) collections:
> > > We would like to use collections, but currently it's not possible to
> > > have a mapper with a collection of interrelated objects (ie. a complex
> > > object graph).
>
> > > But why not using a result map for that? I agree with your point, but
> > > we do not use the ResultHandler to transform or split the created
> > > object into something else; we need it to relate objects within the
> > > result and to control the type of List that is used.
>
> > > I can imaging that you think: 'Why do you need a special kind of
> > > List?': We use a special kind of List that also has 'indexing'
> > > functionality (a kind of map). This allows us to fetch a specific
> > > object from the list by referring to the indexed item (most of the
> > > times the 'id'). When we cannot control the type of List that is used,
> > > then we would not be able to use 'collections' (and our code would be
> > > very inefficient, because we need to transform all List created by
> > > ResultHandlers into our own List implementation).
>
> > > One final note about passing 'context' to a ResultHandler that is
> > > configured in a mapper: When a ResultHandler would have access to the
> > > Mapper arguments, then it would be possible to pass a context object
> > > as one of the mapper parameters. In that case you would have the best
> > > of both worlds: The developer does not need to know which
> > > ResultHandler to use and the mapper method just has a context
> > > argument. Maybe better to discuss this in another topic?
>
> > > On 24 jun, 11:41, Eduardo <[hidden email]> wrote:
> > > > Let me center the objective of this change to let other devs discuss
> > > > it.
>
> > > > Spoiling spring: The magic with DI is that mappers are injected into
> > > > your beans, so you can not use SqlSession at all. This did not work if
> > > > a ResultHandler was needed but that was fixed in issue #322. Now
> > > > mappers can get a ResultHandler so I would say that this problem no
> > > > longer exists.
>
> > > > Spoiling (lazy loaded) collections: You are right here at this point.
> > > > A mapper that needs a specific ResultHandler cannot be reused. But
> > > > should it be?
>
> > > > The question is: what is a ResultHandler for? A ResultHandler just
> > > > gives the results row by row instead of returning them inside a list.
> > > > Mapping has already been applied and result objects are already
> > > > created, populated and passed to the ResultHandler.
>
> > > > ResultHandler could be useful to perform transformations for each
> > > > object but for that purpose you will need some "context", lets say,
> > > > some external data. If the ResultHandler is created by configuration,
>
> ...
>
> meer lezen »