-->
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.  [ 10 posts ] 
Author Message
 Post subject: Trying to understand loading behavior
PostPosted: Sat Jun 25, 2005 11:05 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
I am trying to understand the behavior of hibernate (yep, I'm a newbie), and I'm trying to understand the following situation.

I have a class (Person) that has a one to many association with another class (Address). I have turned off lazy loading and am watching the generated SQL to understand how hibernate loads information from the database. In addition, I have explicitly set fetch="join" on the association to tell hibernate I would like to use an outer join to fetch information on the associated classes.

When I use session.load(), the generated SQL is what I would expect -- a single select created using an outer join. However using HQL (from Person p), hibernate does N+1 selects to get the information.

Is there something I have to change in my configuration to get a single select, or is this just standard behavior for hibernate? Any other tips you could give me on how these mappings should be written would greatly be appreciated as well. I apologize if this is a somewhat stupid question, but, as I said, I'm new. (Hibernate In Action is on its way ;)).

Hibernate version:
3.05

Mapping documents:
Person.hbm.xml:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="net.vickerscraven.learning.hibernate">
   <class name="Person" table="person">
      <id name="id" column="per_id" unsaved-value="null">
         <generator class="native"/>
      </id>
      <property name="firstName" column="per_first_name" not-null="true"/>
      <property name="lastName" column="per_last_name" not-null="true"/>
      <property name="birthDate" column="per_birth_date" not-null="true"/>
      <property name="weightInKilograms" column="per_weight_kg" not-null="true"/>
      <property name="heightInMeters" column="per_height_m" not-null="true"/>
      <set name="addresses" lazy="false" inverse="true" fetch="join">
         <key column="per_id"/>
         <one-to-many class="Address"/>
      </set>
   </class>
</hibernate-mapping>


Address.hbm.xml:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="net.vickerscraven.learning.hibernate">
    <class name="Address" table="address">
       <composite-id>
          <key-many-to-one name="owner" class="Person" column="per_id"/>
          <key-property name="tag" column="tag"/>
       </composite-id>
       <property name="address" column="address" not-null="true"/>
       <property name="address2" column="address2" not-null="false"/>
       <property name="city" column="city" not-null="true"/>
       <property name="state" column="state" not-null="true"/>
       <property name="zip" column="zip"/>
    </class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():
Code:
         person = (Person)session.load(Person.class, new Integer(1));
         System.out.println(person.getFirstName() + " " + person.getLastName());
         
         Query q = session.createQuery("from Person p");
         List results = q.list();
         
         System.out.println(results.size() + " result(s) found.");
         
         Iterator iter = results.iterator();
         
         while (iter.hasNext()) {
            person = (Person)iter.next();
            
            System.out.println(person.getFirstName() + " " + person.getLastName());

            addresses = person.getAddresses();
            
            addressIter = addresses.iterator();
            System.out.println(person.getFirstName() + " has " + addresses.size() + " associated addresses:");
            while (addressIter.hasNext()) {
               address = (Address)addressIter.next();
               
               System.out.println(address.getTag());
            }
         }


Name and version of the database you are using:
PostgreSQL 8

The generated SQL (show_sql=true): (all program output)
Code:
Hibernate: select person0_.per_id as per1_1_, person0_.per_first_name as per2_1_1_, person0_.per_last_name as per3_1_1_, person0_.per_birth_date as per4_1_1_, person0_.per_weight_kg as per5_1_1_, person0_.per_height_m as per6_1_1_, addresses1_.per_id as per1_3_, addresses1_.tag as tag3_, addresses1_.per_id as per1_0_, addresses1_.tag as tag0_, addresses1_.address as address0_0_, addresses1_.address2 as address4_0_0_, addresses1_.city as city0_0_, addresses1_.state as state0_0_, addresses1_.zip as zip0_0_ from person person0_ left outer join address addresses1_ on person0_.per_id=addresses1_.per_id where person0_.per_id=?
Aaron Craven
Hibernate: select person0_.per_id as per1_, person0_.per_first_name as per2_1_, person0_.per_last_name as per3_1_, person0_.per_birth_date as per4_1_, person0_.per_weight_kg as per5_1_, person0_.per_height_m as per6_1_ from person person0_
Hibernate: select addresses0_.per_id as per1_1_, addresses0_.tag as tag1_, addresses0_.per_id as per1_0_, addresses0_.tag as tag0_, addresses0_.address as address0_0_, addresses0_.address2 as address4_0_0_, addresses0_.city as city0_0_, addresses0_.state as state0_0_, addresses0_.zip as zip0_0_ from address addresses0_ where addresses0_.per_id=?
Hibernate: select addresses0_.per_id as per1_1_, addresses0_.tag as tag1_, addresses0_.per_id as per1_0_, addresses0_.tag as tag0_, addresses0_.address as address0_0_, addresses0_.address2 as address4_0_0_, addresses0_.city as city0_0_, addresses0_.state as state0_0_, addresses0_.zip as zip0_0_ from address addresses0_ where addresses0_.per_id=?
Hibernate: select addresses0_.per_id as per1_1_, addresses0_.tag as tag1_, addresses0_.per_id as per1_0_, addresses0_.tag as tag0_, addresses0_.address as address0_0_, addresses0_.address2 as address4_0_0_, addresses0_.city as city0_0_, addresses0_.state as state0_0_, addresses0_.zip as zip0_0_ from address addresses0_ where addresses0_.per_id=?
Hibernate: select addresses0_.per_id as per1_1_, addresses0_.tag as tag1_, addresses0_.per_id as per1_0_, addresses0_.tag as tag0_, addresses0_.address as address0_0_, addresses0_.address2 as address4_0_0_, addresses0_.city as city0_0_, addresses0_.state as state0_0_, addresses0_.zip as zip0_0_ from address addresses0_ where addresses0_.per_id=?
5 result(s) found.
Aaron Craven
Aaron has 1 associated addresses:
home
Christopher Craven
Christopher has 0 associated addresses:
Kleetus Vickers
Kleetus has 0 associated addresses:
John Smith
John has 0 associated addresses:
Katrina Craven
Katrina has 0 associated addresses:


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 26, 2005 1:59 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 7:19 pm
Posts: 2364
Location: Brisbane, Australia
As you have shown, Load uses the mapping directives in its operation. HQL does not so to get what you are after

Code:
select p from Person p left join fetch p.address


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 26, 2005 2:09 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 7:19 pm
Posts: 2364
Location: Brisbane, Australia
Just thought I would include a link to the reference document that will give you a good overview

http://www.hibernate.org/hib_docs/v3/reference/en/html/performance.html#performance-fetching


Top
 Profile  
 
 Post subject: thank you
PostPosted: Sun Jun 26, 2005 2:50 am 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
I see, now.

Sorry. Hadn't dug quite deep enough into the reference yet. (I've been trying to read it, but it's a very dense document, so it's slow reading for me (that is to say, dense in the sense that there's a lot of information, of course).

Thanks so much for being patient with a newbie :-)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 26, 2005 3:33 pm 
Newbie

Joined: Mon May 30, 2005 10:26 am
Posts: 13
Reading the afore-mentioned chapter, it's not clear if fetch="join" would implicitly turn lazy="false". Can we draw such a conclusion?


Top
 Profile  
 
 Post subject: hmmm... not quite what I was looking for after all...
PostPosted: Sun Jun 26, 2005 11:36 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Okay, still not sure I completely understand this, but

Code:
select p from Person p left join fetch p.addresses

doesn't seem to give me quite what I want, because I seem to be getting extra Person objects.

For example, I've got two Person objects, on with two addresses, the other with none.

My results have Person A (with two addresses) twice, and Person B (with no addresses) once each.

What I want is Person A and B (fully loaded with Addresses) only once.

I also tried

Code:
select distinct p from Person p left join fetch p.addresses

with no difference in the results.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 27, 2005 10:17 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Read the FAQ!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 27, 2005 10:20 am 
Newbie

Joined: Mon May 30, 2005 10:26 am
Posts: 13
Please, can you confirm this?
Quote:
it's not clear if fetch="join" would implicitly turn lazy="false". Can we draw such a conclusion?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 27, 2005 10:26 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
acarstoiu wrote:
Please, can you confirm this?
Quote:
it's not clear if fetch="join" would implicitly turn lazy="false". Can we draw such a conclusion?


No. It does not.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 27, 2005 10:57 am 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Quote:
Read the FAQ!


Okay, I found it. I apologize, gavin. As I stated earlier in the post, I am new to this, and am reading as much as I possibly can, but there is a lot of documentation (200+ page reference manual, multiple FAQs, 400 page book on the way,...) to wade through. I simply missed it on my first pass through the FAQs.

Please be patient with me, and I promise I will try very hard not to ask stupid or already-answered questions.

Thanks again!

eagle79


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 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.