-->
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.  [ 6 posts ] 
Author Message
 Post subject: Problem with FetchMode.SELECT
PostPosted: Wed Apr 09, 2008 10:13 am 
Newbie

Joined: Fri Mar 28, 2008 4:50 am
Posts: 3
I have an object with several collection (defined as set) that are all mapped as lazy=true. In some cases I want to search for objects and get several of its relations (with a criteria query). I can not (do not want to) use every time a FetchMode.Join, because this would explode the resultSet. So, for some collections, I thought of using FetchMode.Select. In the doc I found that this also loads the collection, but with a second query, so perfectly what I wanted. But apparently this does not load the collection.
I know I could do the subqueries myself, but I wanted to use this technic also for deep nested relations and their relations, so that becomes complicated. And the FetchMode.Select seemed perfect for this task.
Is there a workaround? Or do I do something wrong?

My version of Hibernate: 3.2.6
I use the Oracle10gDialect

The relevant part of my mapping:
Code:
<class name="User" table="SEC_USER">
    <set name="userRoles" inverse="true" fetch="select">
        <key column="SUS_ID" not-null="true"/>
        <one-to-many class="UserRole"/>
    </set>

I tried with fetch="select", fetch="subselect", without fetch, same with lazy: tried with lazy="true", lazy="false", without lazy. This doesn't seem to make any difference.

The relevant part of the code:
Code:
User user = (User)this.getHibernateSession()
                                .createCriteria(User.class)
                                .createAlias("userRoles", "u")
                                .setFetchMode("u", FetchMode.SELECT)
                                .uniqueResult();

Same here: I tried several things: with createAlias, with createCriteria,... but the problem seems really the FetchMode.SELECT, if I change it in FetchMode.JOIN everything works fine, except that it is in this case (of course) all in one query, which I don't want


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 09, 2008 4:27 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
Hi,
I didn't really understand what you are asking, I'll try to open a discussion:

Quote:
I know I could do the subqueries myself, but I wanted to use this technic also for deep nested relations and their relations,

Are you talking about managed entities?

What do you mean with
Quote:
[..] I want to search for objects and get several of its relations[...] this would explode the resultSet [...]
?
Do you want the data or not? In some way it most be transported from DB to you entities; if you explaing when and how much (data) we could help to define that.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 09, 2008 5:58 pm 
Newbie

Joined: Fri Mar 28, 2008 4:50 am
Posts: 3
Quote:
Are you talking about managed entities?


No, it are just POJO's, but 'deep nested' POJO's: in the example I gave, a user has a Set of Usergroups and Usergroups have themselves Sets of translations and so on (so basically all one-to-many relations). Next to the Set of UserGroups, a User consists also of a Set of UserRoles and a Set of Languages and so on.

So, what I really want to do, is to load one or more users from the database, based on some criteria, with in some cases all the data (the userGroups with translations, the userRoles,...) ideally in one big createCriteria-statement.

I know there are two working options to do so:
1. Define all relations in the mapping as lazy="false". But, I don't want to do that, because I do not always want all related data.
2. create the query and get all related data (for the one-to-many relations) with left join fetch (HQL) or setFechtMode("...", FetchMode.Join) (criteria query). But that doesn't seem as an option to me either, because with too much left joins on one-to-many relations, we would have to deal with the cartesian product problem (see for example http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html). In my example, a fetch join on all relations could still work, but I have other examples where we have objects with a lot more one-to-many relations and several of them again with one-to-many relations. Sot in that case this isn't an option either.

That's why I tried to use the setFetchMode("...", FetchMode.SELECT). In the documentation it is mentioned that this also gets the related data, but in a seperate query and that is exactly what I wanted. But apparently, this doesn't work: the related data is not loaded.
So my question is: how to really load the related data in a seperate query? Do I forget something the way I'm doing it? The relevant piece of code and mapping is in my first post.

Quote:
Do you want the data or not? In some way it most be transported from DB to you entities; if you explaing when and how much (data) we could help to define that.


So, yes I want the data. And in some cases it is a lot of data with a lot of nested one-to-many relations. I thought of using seperate queries for all one-to-many relations of the first level (so for example the userGroups of the user) and a left join fetch on the relations of the second level (so for example the translations of the userGroups).


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 09, 2008 6:07 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
Quote:
No, it are just POJO's, but 'deep nested' POJO's

Well most hibernate applications are like this, the whole problem you are explaining is the reason for hibernate's existence ;-)

Managed entities are POJO's, only Hibernate is automagically adding the data to them when you need it, you just need to use it the correct way so that a connection to the DB stays open until you're finished with the current transaction.

Is this your first hibernate application?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 10, 2008 7:43 am 
Newbie

Joined: Fri Mar 28, 2008 4:50 am
Posts: 3
Quote:
Is this your first hibernate application?


No, this is not my first Hibernate application, but I have to admit, it is the first one that is so complex and big. But, yes, I have some Hibernate experience.

Quote:
you just need to use it the correct way so that a connection to the DB stays open until you're finished with the current transaction.


I know that and I know that when the connection is still open, I can just let Hibernate get the data, for example when I call (in my example) user.getUserGroups() or with Hibernate.initialize. That is a sollution, but in my opinion asking a subselect directly in the base query would be nicer like in my code-example above. In the sollution of getting the data after the query (with getters of with Hibernate.initialize), when I have several users as result, I have to loop through the users and do for each one a getUserGroups(). And so on for relations on this relations. Ok, I can do that, but it seemed a lot nicer to me to use the fetchMode.SELECT. So, my only question was: why does the fetchMode.SELECT doesn't load me the data (see first post for explanation and code)?
The only thing I want to do, is to have a method in my dao that gives me all users corresponding to some criteria with the wanted relations (given as a parameter in the method). And I thought (reading the doc) that this would be possible with a fetchMode.SELECT (why I don't want to use fetchMode.JOIN on all relations, I explained clearly in my posts above).

I also know that (in HQL) I can add the userGroups in my select, so that I get users and userGroups, but that way I would have to loop through the results and see what objects it are, when I want to construct my users as objects with userGroups. OK, that also is a possibility, but that's not my question. I'm just wondering why this doesn't work in one statement, without loops, not using left join fetch on all relations.
I can do it, that's not the point, but I wanted to do it nicely and I don't see why this doesn't work with the fetchMode.SELECT.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 05, 2008 4:01 pm 
Newbie

Joined: Sat Jul 05, 2008 3:57 pm
Posts: 1
I use annotation configuration. You need use subselect fetch.

Example configuration:
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "message_tag", joinColumns = {@JoinColumn(name = "message_id")},
inverseJoinColumns = {@JoinColumn(name = "tag_id")})
@Fetch(value = FetchMode.SUBSELECT)
public Set<Tag> getTags() {
return tags;
}


After this you must access collection before session closed or use not lazy fetch.
http://www.hibernate.org/hib_docs/v3/re ... erformance
19.1
Subselect fetching - a second SELECT is used to retrieve the associated collections for all entities retrieved in a previous query or fetch. Unless you explicitly disable lazy fetching by specifying lazy="false", this second select will only be executed when you actually access the association.


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