-->
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.  [ 3 posts ] 
Author Message
 Post subject: Set.contains acts strangely
PostPosted: Tue Jan 24, 2012 8:00 am 
Newbie

Joined: Tue Jan 24, 2012 7:44 am
Posts: 2
Hi

I have a Entity, that basically declares following:

@Entity
public class MyEntity {
@id
@GeneratedValue
private Long id;

public Long getId() {
return id;
}

public int hashCode() {
return 31 + ((id == null) ? 0 : id.hashCode());
}
}

Then I have another entity, which has
public class OtherEntity {
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
private Set<MyEntity> myEntities;
}

Now I create a new OtherEntity with a set of MyEntities and do following:

entityManager.create(OtherEntity)
boolean test = false;
for(Iterator<MyEntity> iter = otherEntity.getMyEntities().iterator; iter.hasNext()) {
MyEntity entity = iter.next();
test = otherEntity.getMyEntities().contains(entity);
}

Now within the loop, every call to contains(entity) returns false even if I am testing objects that are retrieved from the returned Set itself.

By debugging I have found out that when I first create MyEntity-instances and put them to myEntities-set, it stores them into the Set using hash it gets from object that does not have id-value yet. When I call create on EntityManager, every object in the Set gets an id-number assigned to them, but the hash used in the Set doesn't change. When I then take the object out of the Set and call contains, the HashSet-implementation uses the hashCode() calculated with newly acquired id-numbers and thus fails to find the object in the Set.

Now the question is: is this working as intended? Seems that Hibernate, by assigning objects the generated id value from database (as it should of course do) basically breaks the Set-implementation, because objects hashCode()-value changes but the hash within Set stays the same.


Top
 Profile  
 
 Post subject: Re: Set.contains acts strangely
PostPosted: Tue Jan 24, 2012 10:42 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
This is more or less what can be expected. The root cause is that your implementation is breaking the rules in the contract for the Set interface. This is from the java documentation:

Quote:
Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set.


Since the hash code is part of equals comparisons it is not allowed to change the hash code of an object while it is in a set. This problem is also discussed in the Hibernate documentation http://docs.jboss.org/hibernate/core/3. ... lshashcode which also gives one possible solution.


Top
 Profile  
 
 Post subject: Re: Set.contains acts strangely
PostPosted: Wed Jan 25, 2012 2:28 am 
Newbie

Joined: Tue Jan 24, 2012 7:44 am
Posts: 2
Thanks. That's more or less what I expected after I figured out what was the actual cause of the error. I was just unsure about whether it was the expected behavior.

I see two possible solutions to this issue. Use of business keys as suggested in Hibernate documentation seems to be the safe and thus preferred way to solve this. However there are lots of situations where use of generated id's is not only the most obvious but also simplest way to implement hashCode() and equals(). In these situations one must just remember that newly created Set's can not be trusted until they are either re-retrieved from database or fixed by creating a new Set from the original Set contents.

It is probably needless to say that the latter approach is somewhat dirty and dangerous.


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