-->
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: unique results on set mapping - hibernate bug ?
PostPosted: Sat Mar 22, 2008 11:26 am 
Newbie

Joined: Tue Nov 02, 2004 5:37 pm
Posts: 17
Greetings to all,

i have come across this issue. I have a class employee and a class department. There is a set mapping on class employee (pointing to many departments through an one to many mapping) and a many to one mapping at the declaration of class department to class employee.

The problem is if i query for employees and get an employee that has 2 or 3 departments , i get the same employee row 2 - 3 times instead of a unique result. So the query gives me back a cartesian result.

i.e.
John Smith Accounting
John Smith Marketing.

At the moment i iterate over the results and use a hashmap to put only the unique rows. I do not think that this is the best way to go though.

How can i get only the unique rows of the employee object ? Should i initialize a HashSet instead of a List ? Is this somehow "dangerous" ?

Thank you very much. Your answers are appreciated.

Best Regards,

Leon


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 22, 2008 4:48 pm 
Newbie

Joined: Tue Nov 02, 2004 5:37 pm
Posts: 17
Actually what is more worrying is that it returns a list that contains the same object twice.

John Smith - with deps ( Account Marketing )
John Smith - with deps ( Account Marketing )

so what it is doing is :

it fetches John Smith once with all the deps and then it fetches the same object again with all deps... I think the number of same objects depends on the number of the deps that they have ...

Any thoughts guys ?

The mapping is :

Person class
....
<set name="department">

<key column="p_id" />

<one-to-many class="Department" />

</set>

Department class
....
<many-to-one name="person" class="Person" column="p_id" />

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 22, 2008 8:42 pm 
Beginner
Beginner

Joined: Fri Aug 24, 2007 4:46 am
Posts: 36
Location: Bielefeld / Germany
Please try to declare the many-valued end of the one-to-many as inverse="true".

E.g.

<set name="department" inversed="true">
...
</set>

Please read:

http://www.hibernate.org/hib_docs/v3/re ... tions.html
=> 6.3.2. Bidirectional associations


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 23, 2008 10:19 am 
Newbie

Joined: Mon Dec 11, 2006 8:28 am
Posts: 13
I'm having the same problem with a couple of classes that use annotations rather than mapping files, and that have a one-way OneToMany relationship. I've read the link you posted, but I didn't glean a solution from there.

My classes look like this:

@Entity
@Table(name = "users")
public class UsersEntity {
private int userid;

@Id
@Column(name = "userID", nullable = false, length = 10)
public int getUserid() {
return userid;
}

public void setUserid(int userid) {
this.userid = userid;
}

private String userusername;

@Basic
@Column(name = "userUsername", nullable = false, length = 25)
public String getUserusername() {
return userusername;
}

public void setUserusername(String userusername) {
this.userusername = userusername;
}

private Collection<EnumdomainmappingEntity> enumdomainmappingsByUserid;

@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "userID")
public Collection<EnumdomainmappingEntity> getEnumdomainmappingsByUserid() {
return enumdomainmappingsByUserid;
}

public void setEnumdomainmappingsByUserid(Collection<EnumdomainmappingEntity> enumdomainmappingsByUserid) {
this.enumdomainmappingsByUserid = enumdomainmappingsByUserid;
}
}

@Entity
@Table(catalog = "hsmichael", name = "enumdomainmapping")
public class EnumdomainmappingEntity {
private int id;

@Id
@Column(name = "id", nullable = false, length = 8)
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

private String enumdomain;

@Basic
@Column(name = "enumDomain", nullable = false, length = 100)
public String getEnumdomain() {
return enumdomain;
}

public void setEnumdomain(String enumdomain) {
this.enumdomain = enumdomain;
}
}

Hibernate generates the following join select:

select this_.userID as userID21_1_, this_.userUsername as userUser2_21_1_, enumdomain2_.userID as userID3_, enumdomain2_.id as id3_, enumdomain2_.id as id20_0_, enumdomain2_.enumDomain as enumDomain20_0_ from users this_ left outer join enumdomainmapping enumdomain2_ on this_.userID=enumdomain2_.userID order by this_.userUsername asc

which, with my test data, gives 5 rows corresponding to the 5 enumdomainmappings linked to the 1 usersentity. The list that I get has *5* UsersEntity objects, each of which correctly contains 5 Enumdomainmappings objects.

BTW, based on what I read I tried different values for "nullable" in the JoinColumn. I also delved deep into the code in the debugger, but I don't see where it's supposed to collapse multiple copies of the same item.

Your help is appreciated.

Michael

_________________
Michael Berkowitz


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 23, 2008 12:57 pm 
Newbie

Joined: Tue Nov 02, 2004 5:37 pm
Posts: 17
Hi guys,

i think i have figured it out. Actually it is documented on this page : http://www.hibernate.org/117.html

The left join fetch on a set ( one to many ) fetches the values once from the db. But due to the outer join it returns the same instance of the object more than once. It is not that it queries the db more than one time or returns a cartesian result. Actually a Hashset is a very logical class type to use since it will only have unique references to the objects.

The article offers many solutions i.e. use "select distinct e from Employee ..." and then use a List with no problem ...

I am not sure whether someone from the development team can confirm the above, but it should be correct...

Thanks for your replies.

Regards,


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 24, 2008 4:49 am 
Newbie

Joined: Mon Dec 11, 2006 8:28 am
Posts: 13
Thanks!

In fact, the answer to my question was in http://www.hibernate.org/117.html#A12 (amid a bunch of warnings that maybe I just don't understand SQL...), and it's the type of thing that I wouldn't have found by debugging into the Hibernate code, so you were a great help.

I simply added
Code:
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
before my
Code:
.list()
and Hiberante took care of removing the duplicates for me.

_________________
Michael Berkowitz


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.