-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 
Author Message
 Post subject: find() generates 1 query but createQuery() generates 3
PostPosted: Wed Mar 18, 2009 11:54 pm 
Newbie

Joined: Mon Apr 02, 2007 7:19 am
Posts: 5
Hibernate version: 3.3.1

Name and version of the database you are using: Derby Embedded

<property name="show_sql">false</property>
<property name="format_sql">true</property>
<property name="use_outer_join">true</property>
<property name="hibernate.max_fetch_depth">5</property>


table XCPTN has two Many-To-One relationship with FIRM_REF and XCPTN_TYPE

if I run query this way:
Code:
Xcptn x = em.find(Xcptn.class, 1000L);

There is only ONE query:
Code:
select
        xcptn0_.ID as ID0_2_,
        xcptn0_.FIRM_ID as FIRM3_0_2_,
        xcptn0_.MKT_CLS as MKT2_0_2_,
        xcptn0_.TYPE_ID as TYPE4_0_2_,
        firmref1_.ID as ID2_0_,
        firmref1_.FIRM_MP_ID as FIRM2_2_0_,
        xcptntype2_.ID as ID1_1_,
        xcptntype2_.NAME as NAME1_1_
    from
        XCPTN xcptn0_
    left outer join
        FIRM_REF firmref1_
            on xcptn0_.FIRM_ID=firmref1_.ID
    left outer join
        XCPTN_TYPE xcptntype2_
            on xcptn0_.TYPE_ID=xcptntype2_.ID
    where
        xcptn0_.ID=?


But if I run it this way:
Code:
Query q = em.createQuery("from Xcptn x where x.id=1000");

There are three queries:
Code:
select
        xcptn0_.ID as ID0_,
        xcptn0_.FIRM_ID as FIRM3_0_,
        xcptn0_.MKT_CLS as MKT2_0_,
        xcptn0_.TYPE_ID as TYPE4_0_
    from
        XCPTN xcptn0_
    where
        xcptn0_.ID=1000
--------------------------
select
        firmref0_.ID as ID2_0_,
        firmref0_.FIRM_MP_ID as FIRM2_2_0_
    from
        FIRM_REF firmref0_
    where
        firmref0_.ID=?
-------------------------
select
        xcptntype0_.ID as ID1_0_,
        xcptntype0_.NAME as NAME1_0_
    from
        XCPTN_TYPE xcptntype0_
    where
        xcptntype0_.ID=?


How to force Hibernate to use one query with joins instead of three simple?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 19, 2009 3:23 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Quote:
How to force Hibernate to use one query with joins instead of three simple?


You'll need to specify this in your HQL query. Something like:

Code:
from Xcptn x left join fetch x.FIRM_REF fref left join fetch fref.XCPTN_TYPE where x.id=1000


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 19, 2009 7:57 am 
Newbie

Joined: Mon Apr 02, 2007 7:19 am
Posts: 5
nordborg wrote:
Quote:
How to force Hibernate to use one query with joins instead of three simple?


You'll need to specify this in your HQL query. Something like:

Code:
from Xcptn x left join fetch x.FIRM_REF fref left join fetch fref.XCPTN_TYPE where x.id=1000


Well, I mean automatically, not writing "left join fetch". I think that runnig one SQl query is cheaper then three. Why hibernate uses one big query in the first scenario and three small queries in the second one? in both cases it is just search by xcptn.id.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 19, 2009 8:24 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Because that is how HQL works. It will only fetch what you have specified in the HQL. It ignores whatever you have put in the "fetch" attribute of your mapping files. I assume you have fetch="join" since that is what is causing the first example to select everything with one query instead of three.

The reason that you are seing additional selects in the second example with HQL is probably because you have have disabled the use of proxies for the FIRM_REF and XCPTN_TYPE entities.

If you need all three entities (Xcptn, FIRM_REF and XCPTN_TYPE) and if you want to use HQL that only generates one select, you'll need to specify "left join fetch" in the HQL.

If you only need the Xcptn entity and want to use HQL and want to avoid the extra select statements you'll need to enable proxies for FIRM_REF and XCPTN_TYPE. Or... as an option, you could setup a second-level cache for FIRM_REF and XCPTN_TYPE.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 19, 2009 8:48 am 
Newbie

Joined: Mon Apr 02, 2007 7:19 am
Posts: 5
nordborg wrote:
Because that is how HQL works. It will only fetch what you have specified in the HQL. It ignores whatever you have put in the "fetch" attribute of your mapping files. I assume you have fetch="join" since that is what is causing the first example to select everything with one query instead of three.

The reason that you are seing additional selects in the second example with HQL is probably because you have have disabled the use of proxies for the FIRM_REF and XCPTN_TYPE entities.

If you need all three entities (Xcptn, FIRM_REF and XCPTN_TYPE) and if you want to use HQL that only generates one select, you'll need to specify "left join fetch" in the HQL.

If you only need the Xcptn entity and want to use HQL and want to avoid the extra select statements you'll need to enable proxies for FIRM_REF and XCPTN_TYPE. Or... as an option, you could setup a second-level cache for FIRM_REF and XCPTN_TYPE.


Thank you for explanation.

But still do not understand why hibernate goes "not optimal" way running three queries instead of one.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 19, 2009 8:55 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Quote:
But still do not understand why hibernate goes "not optimal" way running three queries instead of one.


Beacuase you issued a query that told Hibernate to do it that way.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 21, 2009 1:39 am 
Newbie

Joined: Mon Apr 02, 2007 7:19 am
Posts: 5
nordborg wrote:
Quote:
But still do not understand why hibernate goes "not optimal" way running three queries instead of one.


Beacuase you issued a query that told Hibernate to do it that way.


Well. XCPNT entity has two @ManyToOne relationship with XCPTN_TYPE and FIRM_REF. By default @ManyToOne has fetch=EAGER. So if I look for XCPTN with id = 1000 JPA impl should fill entities on the other side of @ManyToOne. In this case there are XCPTN_TYPE and FIRM_REF.
And of course Hibernate does it. The question why it does it in "Not optimal" way, using three queries instead of one?

Why I need to write long query with left join fetch if I already specify relationships and fetches via annotations?

Is there any way to use small queries or whatever which relies on Relationship annotation information.

E.g. I need to get xcptn with xcpnt.type.name = "type1" how to do it easiest way? Plus I want that entities on the other side of fetch=eager relationship will be filled and I do not want to write join logic by hand anywhere except from relationship annotations. Plus I want that JPA impl does smart queries, and minimize their number.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 21, 2009 5:25 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Quote:
The question why it does it in "Not optimal" way, using three queries instead of one?


I don't know how many times I need to repeat that this is because your HQL tells Hibernate to do it that way. If you want Hibernate to fetch everything in one SQL, you'll need to say that in your HQL by using "join fetch". Fetch settings in your mappings files/annotations are in most cases not used by HQL. What is non-optimal for you, may not be for someone else. It all depends on a lot of other things, such as how your proxies and second-level cache are configured etc. You can find more information here: http://www.hibernate.org/hib_docs/v3/re ... ing-custom


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.