Sorry for the late response. I've been looking through the fix for HHH-5163
[1] to jog my memory.
Here are some reasons why CacheableResultTransformer is important when
caching query results:
1) The same SQL can be generated when associations are joined as when
associations are fetched, but what gets cached is different. The cached
results exclude fetched associations. QueryKey needs to contain the proper
CacheableResultTransformer to indicate which tuple elements are cached to
distinguish the differing results.
2) IIRC, the tuple elements that got cached by the legacy Criteria and HQL
were inconsistent, and I believe that in some cases the ResultTransformer
was applied before caching the value, which added to problems assembling
the query results (HHH--2463). CacheableResultTransformer ensured that what
got cached was consistent (excluding fetched values), and ensured that rows
were untransformed (padded with nulls where fetches were) and
re-transformed (if necessary) by a specified transformer as necessary.
I added lots of tests for this change, so I think we will find out quickly
if something gets broken.
Steve, I'm not completely following your discussion. Some pseudocode would
help.
Let me know if you need more details.
[1]
On Tue, Sep 13, 2016 at 5:05 PM, Steve Ebersole <steve(a)hibernate.org> wrote:
Hmmm there is an interesting aspect to Tuple + TupleTransformer..
both
expect to get the root selection aliases and would naturally expect those
to match in length to the values to transform. Basically only one can
"consume" the aliases.
I think that because Tuple is a "higher precedence" (it defines the result
type) it ought to win that battle. But then that is inconsistent for
TupleTransformer. IMO either we let Tuple consume the aliases or we
disallow this combo.
On Tue, Sep 13, 2016 at 6:00 PM Steve Ebersole <steve(a)hibernate.org>
wrote:
> So here is the path I am following initially.. It is straightforward to
> explain to a user which I like.
>
> In terms of processing each "row" in a result there is the RowTransformer
> contract I mentioned earlier, or maybe I mentioned on HipChat. I added
the
> capability for RowTransformer to be nested, specifically I defined 2
> levels:
>
> 1. an implicit RowTransformer. This is resolved based on the
> following chart:
> 1. If there is a resultType and it is Object[].class we do a "pass
> thru"
> 2. If there is a resultType and it is Tuple.class we do use a
> RowTransformer adapter that builds a Tuple
> 3. If there is just one selection we transform the Object[] by
> returning just row[0]
> 2. a RowTransformer adapter for TupleTransformer, if specified
>
> And just a word on dynamic-instantiation here.. it is actually done prior
> to any of this. In fact, in 6.0 a dynamic-instantiation is no different
> that other selectable expressions.
>
>
>
> On Tue, Sep 13, 2016 at 9:19 AM Steve Ebersole <steve(a)hibernate.org>
> wrote:
>
>> So again, this all boils down to the interplay with
>> (Result|Tuple|ResultList)Transformer, dynamic instantiations, and
>> result-types.
>>
>> So let's look at some specific cases...
>>
>> First some cases I think are perfectly valid:
>>
>> session.createQuery( "select new map(...) ...", Map.class ) - returns
a
>> List<Map<String,?>>
>> session.createQuery( "select new list(...) ...", List.class ) -
returns
a
>> List<List> (rather than List<Object[]>)
>> session.createQuery( "select new DTO(...), DTO.class ) - returns a
>> List<DTO>
>>
>> Ok, so I cheated there by not including transformers :) So let's look
at
>> adding transformers into this mix[1].
>>
>> session.createQuery( "select new map(...) ...", Map.class )
>> .setTupleTransformer( new TupleTranformer<SomeNonMap>() {...} )
>>
>> this one is illegal. It defines the Query resultType as Map, but the
>> applied TupleTranformer is transforming those to SomeNonMap -> CCE.
>> This should be either:
>>
>> session.createQuery( "select new map(...) ...", SomeNonMap.class )
>> .setTupleTransformer( new TupleTranformer<SomeNonMap>() {...} )
>>
>> or (non-typed):
>>
>> session.createQuery( "select new map(...) ..." )
>> .setTupleTransformer( new TupleTranformer<SomeNonMap>() {...} )
>>
>> In both of those cases, the TupleTranformer is handed a Object[] where
>> the only element is the Map.
>>
>> I guess too that defines the blueprint for what is and what is not
>> supported and how the various pieces apply.
>>
>>
>> But I am still not sure about the semantic wrt TupleTransformer and/or
>> dynamic-instantiation in combination with Tuple. I kind of think those
>> should just be illegal combos:
>>
>> session.createQuery( "select ...", Tuple.class )
>> .setTupleTransformer( () -> ... )
>>
>> Unless the TupleTransformer is building a Tuple, I that is a bad combo
>> for sure.
>>
>> I thik dynamic-instantiation and TupleTransformer is ok:
>>
>> session.createQuery( "select new DTO(...) ..." )
>> .setTupleTransformer( () -> ... )
>>
>> Here the TupleTransformer would get Object[] with the long element being
>> the DTO; the "query result" is whatever the TupleTransformer returns.
>>
>> Any other specific combos we should clarify?
>>
>>
>>
>> [1] I am using the new TupleTransformer and ResultListTransformer
>> breakdowns I have defined on 6.0 :
>>
https://gist.github.com/sebersole/bc721caa20a5e4a97cbde44567b0b2ea
>>
>>
>>
>> On Tue, Sep 13, 2016 at 8:52 AM Steve Ebersole <steve(a)hibernate.org>
>> wrote:
>>
>>> On Tue, Sep 13, 2016 at 2:26 AM Gunnar Morling <gunnar(a)hibernate.org>
>>> wrote:
>>>
>>>> > Between dynamic-instantiation, Tuple-handling...
>>>>
>>>> To be sure, WDYM by "tuple-handling"?
>>>>
>>>
>>> javax.persistence.Tuple
>>>
>>> So I gave just one example earlier of how all of these things do not
>>> necessarily fit together in inherently obvious ways. Some combinations
>>> I think are ok; others are not. In sitting here and trying to describe
>>> this to a user from a documentation perspective, it is not a simple
>>> explanation.
>>>
>>> I'll follow up with a separate reply that covers those combos for
>>> discussion.
>>>
>>>
>>> One use case for result transformers are full-text searches executed
>>>> through Hibernate Search's Session extension FullTextSession (see
[1]).
>>>>
>>>> For full-text searches we don't use HQL/JPQL, so the "new
..." syntax
>>>> cannot be used, but I don't know about tuple-handling.
>>>>
>>>
>>> Well for sure you do not allow the user to use HQL/JPQL. But I'd have
>>> to assume that under the covers you handle resolving that FullTextQuery
>>> yourself from the indexes - which means this is not even a ORM Query
at all
>>> and what we do with ResultTransformer in ORM in regards to Query is
>>> completely irrelevant for you. In other words I would have to think
that
>>> Search itself is applying that ResultTransformer in your example, not
ORM.
>>> Very different.
>>>
>>
_______________________________________________
hibernate-dev mailing list
hibernate-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev