-->
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.  [ 7 posts ] 
Author Message
 Post subject: one-to-one/many-to-one fetch="join" not working.
PostPosted: Fri Jun 02, 2006 7:00 pm 
Regular
Regular

Joined: Thu Jul 08, 2004 1:21 pm
Posts: 68
Location: Recife - Pernambuco - Brazil
Hibernate version: 3.1.3

Name and version of the database you are using: Postgres 8.1

Hello, I'm having a strange problem with one-to-one relationship. I having the following mappings:
People.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>
   
   <class name="com.project.model.People" batch-size="5">
   
      <id name="id" unsaved-value="null">
         <generator class="native"/>
      </id>
      
      <property name="nome" />
      <property name="idade" />
      
   </class>
   
</hibernate-mapping>

Group.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>
   
   <class name="com.project.model.Group" table="tgroup">
   
      <id name="id" unsaved-value="null">
         <generator class="native"/>
      </id>
      
      <property name="description" />
      
      <set name="roles" batch-size="5">
         <key column="id_group" />
         <many-to-many class="com.project.model.Role" column="id_role" />
      </set>
      
   </class>
   
</hibernate-mapping>

User.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>
   
   <class name="com.project.model.User" table="tuser">
   
      <id name="id" unsaved-value="null">
         <generator class="foreign">
            <param name="property">people</param>
         </generator>
      </id>
      
      <one-to-one name="people" fetch="join" />
      <many-to-one name="group" fetch="join" column="tgroup" />
      
      <property name="login" />
      <property name="password" />
      
   </class>
   
</hibernate-mapping>

When I execute a query like "from User user where user.id = 1, hibernate executes the sql below:
Code:
Hibernate: select user0_.id as id4_, user0_.tgroup as tgroup4_, user0_.login as login4_, user0_.password as password4_ from tuser user0_ where user0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select group0_.id as id0_0_, group0_.description as descript2_0_0_ from tgroup group0_ where group0_.id=?

But, with fetch="join" set at people and group relationships, the two last queries must not be executed, am I right? I have tried to set hibernate.max_fetch_depth to "2", but this doesn't work too. Anyway, when I retrieve User objects using join fetch in a HQL, all works fine:
Code:
String query = "from User user join fetch user.people people where user.id=5";
Session session = (Session) persistenceSession;
            
return session.createQuery(query).list();

This code generates only this SQL:
Code:
Hibernate: select user0_.id as id4_0_, people1_.id as id2_1_, user0_.tgroup as tgroup4_0_, user0_.login as login4_0_, user0_.password as password4_0_, people1_.nome as nome2_1_, people1_.idade as idade2_1_ from tuser user0_ inner join People people1_ on user0_.id=people1_.id where user0_.id=5

If I put a join fetch to group, this will works properly too. So, what is wrong with my mappings/configurations? Why the fetch="join" attributes are not working?

Kind Regards,

_________________
Marcos Silva Pereira
http://blastemica.blogspot.com


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 04, 2006 6:33 am 
Expert
Expert

Joined: Thu Sep 22, 2005 10:29 am
Posts: 285
Location: Almassera/Valencia/Spain/EU/Earth/Solar system/Milky Way/Local Group/Virgo Supercluster
try with:

Code:
<one-to-one name="people" fetch="join" lazy="false" />
<many-to-one name="group" fetch="join" column="tgroup" lazy="false" />


What's happened?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 05, 2006 4:30 pm 
Regular
Regular

Joined: Thu Jul 08, 2004 1:21 pm
Posts: 68
Location: Recife - Pernambuco - Brazil
pepelnm wrote:
try with:

Code:
<one-to-one name="people" fetch="join" lazy="false" />
<many-to-one name="group" fetch="join" column="tgroup" lazy="false" />


What's happened?

I get the same:
Code:
Hibernate: select user0_.id as id4_, user0_.tgroup as tgroup4_, user0_.login as login4_, user0_.password as password4_ from tuser user0_ where user0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select group0_.id as id0_0_, group0_.description as descript2_0_0_ from tgroup group0_ where group0_.id=?

I think that this configuration should be redundant, because, if I have fetch join, lazy should not be true in any case. Anyway, this configuration seems to be in favor of lazy="false". If I execute the following query without lazy="false" the SQL is like I show below:
HQL: from User user where user.id > 5 // I have 5 registries that matchs with it
Code:
Hibernate: select user0_.id as id4_, user0_.tgroup as tgroup4_, user0_.login as login4_, user0_.password as password4_ from tuser user0_ where user0_.id>?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?

A note about it, groups are clearly loaded in lazy mode. If I not made access to a group, it is not load automatically in join as expected. So, if I put lazy="false", the SQL generated is:
Code:
Hibernate: select user0_.id as id4_, user0_.tgroup as tgroup4_, user0_.login as login4_, user0_.password as password4_ from tuser user0_ where user0_.id>?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select group0_.id as id0_0_, group0_.description as descript2_0_0_ from tgroup group0_ where group0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select group0_.id as id0_0_, group0_.description as descript2_0_0_ from tgroup group0_ where group0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select group0_.id as id0_0_, group0_.description as descript2_0_0_ from tgroup group0_ where group0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select group0_.id as id0_0_, group0_.description as descript2_0_0_ from tgroup group0_ where group0_.id=?
Hibernate: select people0_.id as id2_0_, people0_.nome as nome2_0_, people0_.idade as idade2_0_ from People people0_ where people0_.id=?
Hibernate: select group0_.id as id0_0_, group0_.description as descript2_0_0_ from tgroup group0_ where group0_.id=?

As I said before, seems that lazy="false" override fetch="join". So, the question is, how to configure mappings to load one-to-one and many-to-one in join mode?

Kind Regards,

_________________
Marcos Silva Pereira
http://blastemica.blogspot.com


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 05, 2006 9:05 pm 
Senior
Senior

Joined: Sun Jun 04, 2006 1:58 am
Posts: 136
Hibernate is able to fetch only one collection per SQL select , so it isnt possible to declare multiple collections belonging to same persistent calls with fetch="join"


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 05, 2006 9:35 pm 
Regular
Regular

Joined: Thu Jul 08, 2004 1:21 pm
Posts: 68
Location: Recife - Pernambuco - Brazil
scarface wrote:
Hibernate is able to fetch only one collection per SQL select , so it isnt possible to declare multiple collections belonging to same persistent calls with fetch="join"

Ok, I know that, but this case is not about collections, is about one-to-one and many-to-one relationships. I am not at work at now, but I suspect that Hibernate will load group and people (this is a wrong name, it must be Person) only when I use load/get methods. I will try and report it later.

Kind Regards,

_________________
Marcos Silva Pereira
http://blastemica.blogspot.com


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 07, 2006 1:00 pm 
Regular
Regular

Joined: Thu Jul 08, 2004 1:21 pm
Posts: 68
Location: Recife - Pernambuco - Brazil
Well, as I suspect before, only load/get do join fetch:
Code:
Session session = getSession();
User user = (User)session.get(User.class, new Long(1));

This produces the following SQL:
Code:
select
   user0_.id as id4_2_,
   user0_.tgroup as tgroup4_2_,
   user0_.login as login4_2_,
   user0_.password as password4_2_,
   people1_.id as id2_0_,
   people1_.nome as nome2_0_,
   people1_.idade as idade2_0_,
   group2_.id as id0_1_,
   group2_.description as descript2_0_1_
from
   tuser user0_
left outer join
   People people1_
on
   user0_.id=people1_.id
left outer join
   tgroup group2_
on
   user0_.tgroup=group2_.id
where
   user0_.id=?

Kind Regards,

_________________
Marcos Silva Pereira
http://blastemica.blogspot.com


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 07, 2006 3:29 pm 
Regular
Regular

Joined: Thu Sep 22, 2005 1:53 pm
Posts: 88
Location: Rio de Janeiro
Take a look at the follwing in the Hibernate documentation:

19.1.2. Tuning fetch strategies

Here it says:

Quote:
The fetch strategy defined in the mapping document affects:

retrieval via get() or load()

retrieval that happens implicitly when an association is navigated

Criteria queries

HQL queries if subselect fetching is used

No matter what fetching strategy you use, the defined non-lazy graph is guaranteed to be loaded into memory. Note that this might result in several immediate selects being used to execute a particular HQL query.

Usually, we don't use the mapping document to customize fetching. Instead, we keep the default behavior, and override it for a particular transaction, using left join fetch in HQL. This tells Hibernate to fetch the association eagerly in the first select, using an outer join. In the Criteria query API, you would use setFetchMode(FetchMode.JOIN).

If you ever feel like you wish you could change the fetching strategy used by get() or load(), simply use a Criteria query, for example:


Seems to me that what is said here is exactly what you are expriencing.

Good luck

_________________
DonĀ“t forget to rate!


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