-->
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.  [ 11 posts ] 
Author Message
 Post subject: Need help with resolving n+1 query problem for simple case
PostPosted: Thu Feb 19, 2009 11:53 pm 
Newbie

Joined: Thu Feb 19, 2009 11:37 pm
Posts: 10
I have a very simple case of two entities: UserIdentity and Student. Each UserIdentity related to exactly one Student. I have created a OneToOne association between UserIdentity and Student.

When I load the UserIdentity table, I want Hibernate to eagerly load all the corresponding Student as well. This is working fine - however, I see in the log that it is generating n+1 queries (1 query for getting all the UserIdentity, and then n queries for getting the Student of each UserIdentity)

My goal is to have all the Student retrieved in ONE query.

I have tried using FetchType.JOIN - but it doesn't help.

Here is my mapping - can someone please tell me whats wrong?
(I have looked through the FAQs, docs and HibernateInAction book - but can't nail this down)

@Entity
@Table(name = "userIdentity", catalog = "ubc")
public class UserIdentity {
@Id
private String username;
private String password;
private String permissions;

@OneToOne
@JoinColumn(name = "STUDENT_ID")
@Fetch(FetchMode.JOIN)
private Student student;

......
.....
}

@Entity
@Table(name = "students", catalog = "ubc")
public class Student {
@Id
private String id;
private String firstName;
private String lastName;
private String middleInitial;

...
...
}


FYI - I use EntityQuery to get the UserIdentity table:
List<UserIdentity> userIdentityList = userIdentityQuery.getResultList();


@Name("userIdentityQuery")
public class UserIdentityQuery extends EntityQuery<UserIdentity> {

@Override
public String getEjbql() {
return "select userIdentity from UserIdentity userIdentity";
}

}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 4:06 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Use this query:

Code:
select userIdentity from UserIdentity userIdentity fetch join useridentity.student


The FetchMode setting is not used when you are loading things with HQL.


Top
 Profile  
 
 Post subject: it worked...
PostPosted: Fri Feb 20, 2009 2:47 pm 
Newbie

Joined: Thu Feb 19, 2009 11:37 pm
Posts: 10
Thanks for your reply - it worked. FYI - I had to slightly change your suggested query to "join fetch" instead of "fetch join".


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 3:15 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Quote:
I had to slightly change your suggested query to "join fetch" instead of "fetch join".


Ah... of course. Sorry for that.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 5:39 pm 
Newbie

Joined: Thu Feb 19, 2009 11:37 pm
Posts: 10
May I ask a quick follow up question?
Its regarding:
"The FetchMode setting is not used when you are loading things with HQL."

In practice, won't tables always be loaded in response to a HQL query? Can you please help me visualize a case when a table is loaded automatically?

Thanks in Advance!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 7:22 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
The following doesn't use HQL:

* Session.get(),
* Criteria queries
* Navigating to an associated item or collection

See also: http://www.hibernate.org/hib_docs/v3/re ... ing-custom


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2009 7:42 pm 
Newbie

Joined: Thu Feb 19, 2009 11:37 pm
Posts: 10
OK, got it... thanks again :)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 21, 2009 4:40 pm 
Newbie

Joined: Thu Feb 19, 2009 11:37 pm
Posts: 10
Is it possible to have a "cascading fetch"?

For instance, in the example above of UserIdentity and Student - a Student has an association with another entity called "Purchase"

@Entity
public class Purchase {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long purchaseId;
private Date purchaseDate;
private String status;

@ManyToOne
@JoinColumn(name="STUDENT_ID")
private Student student;
...
...

}

@Entity
@Table(name = "students", catalog = "ubc")
public class Student {
@Id
private String id;
private String firstName;
private String lastName;
private String middleInitial;

@OneToMany (mappedBy = "student")
private Set<Purchase> purchases = new HashSet<Purchase>();
...
...
}


Is it possible to extend the query:
"select userIdentity from UserIdentity userIdentity join fetch userIdentity.student"

to make it also "fetch" the "purchases" for each student - in a single SQL Select query??!

Once more - thanks very much in advance!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 21, 2009 5:01 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Yes it is. There are several examples in the Hibernate documentation. http://www.hibernate.org/hib_docs/v3/re ... joins.html


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 21, 2009 6:05 pm 
Newbie

Joined: Thu Feb 19, 2009 11:37 pm
Posts: 10
That worked!

Here is my query:
"select distinct userIdentity from UserIdentity userIdentity join fetch userIdentity.student s join fetch s.purchases"

Thanks a ton for all your help!! I really appreciate it :)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 21, 2009 6:07 pm 
Newbie

Joined: Thu Feb 19, 2009 11:37 pm
Posts: 10
This cleanly resolves the n+1 query issue....very cool!


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