-->
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.  [ 13 posts ] 
Author Message
 Post subject: equals() and hashCode() philosophy.
PostPosted: Fri Oct 29, 2004 12:55 pm 
Beginner
Beginner

Joined: Mon Sep 27, 2004 4:28 pm
Posts: 44
In my last go-around with our domain model (using entity beans) our equals() implementation only took into account the surrogate primary key value.

This was problematic for clients while creating new objects (which would only compare references), and in moving the code to hibernate I took note of the HiA book's warning that an implementation of hashCode() which involved the surrogate key would break the contract Objects have with collections during a Hibernate cascade-save.

I was also enamored with the idea of using a natural key for equals() and hashCode().

However, I couldn't get over the fact that equals() wouldn't use the surrogate t if it was present. After all, natural keys can change.

At any rate, after going back and forth for a while I came up with an implementation I wanted to throw out there for input [read: criticism] :

I'm thinking that equals() will compare surrogate keys if they exist, natural keys if they don't.

The hashCode() implementation will use only the natural key values in it's algorithm.

If for some reason I have two entities in a collection with the same natural key, but different primary keys, their hash codes will be the same, but that's okay, isn't it? It won't happen often, and their equals() implementations will report them unique.

This way I don't break the contract I have with Set, cascade saves are okay, and I can tell that a persisted entity and it's altered clone are two versions of the same row.

Thoughts?


Top
 Profile  
 
 Post subject: equals and HashCode
PostPosted: Fri Nov 05, 2004 10:56 am 
Newbie

Joined: Wed May 19, 2004 1:25 pm
Posts: 11
I avoid the problem by having the original objects hashCode stored to the database. This saves me a whole lot of pain. Fortunately I'm in a position to make this decision. Companies with an existing database will not be so kind as to include a hashCode field.

I do think its kinda wastefull storing hashCode but it suites my ease-of-use scenarios.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 06, 2004 7:12 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
This is not safe since your equals results could change between before and after hibernate.save() has been done.

Remember that the "natural key" used in equals has to be unique during the JVM instance life time (not the whole life of the application)

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 06, 2004 10:59 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
emmanuel wrote:
Remember that the "natural key" used in equals has to be unique during the JVM instance life time (not the whole life of the application)


aarh - not completly true, is it?

It only need to be stable while it is inside something (like a Collection or Map) that expects it to be stable.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 07, 2004 12:37 pm 
Beginner
Beginner

Joined: Mon Sep 27, 2004 4:28 pm
Posts: 44
I guess my reasoning on that is that my hashCode implementation won't change (during a cascade-save for instance). My equals() implementation will change, but I can guarantee that it won't break the transitive nature of hashCode() or equals().. So while I'm technically breaking the contract, I'm not doing so in spirit.

I dunno. Buy that?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 01, 2004 10:45 am 
Newbie

Joined: Wed Dec 01, 2004 10:23 am
Posts: 4
I am consider to use ArraySet or LinkedSet to bypass the hashCode() issue.

Any comments?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 01, 2004 10:53 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
yes - how ? ;)

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 01, 2004 9:12 pm 
Newbie

Joined: Wed Dec 01, 2004 10:23 am
Posts: 4
The root problem:
a) cal hashCode() using your PK
b) add your new object to a HashSet
c) call session.save() which assign value to your PK
d) HashSet lost your object because your hashCode() is changed

My solution is to use ArraySet or LinkedSet which never call to hashCode(). The only problem of ArraySet/LInkedSet is slower because it do not use hashCode().

The ArraySet should look like this:
http://cvs.sourceforge.net/viewcvs.py/t ... &view=auto

I want to hear some comments before I do implement this solution to my program....

NB: Anyone know where is the best ArrySet or LinkedSet?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 02, 2004 2:19 am 
Expert
Expert

Joined: Tue Oct 05, 2004 9:45 am
Posts: 263
just a perhaps stupid question ...

but why not use business-fields for 'hashCode'? If the pk is generated i think it's not really the best solution for 'hashCode'-calculation ... and if the pk is assigned by application, it's set before your save/update-call and therefore no problem ...

or do i miss something?

gtx
curo


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 02, 2004 2:59 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
the only issue with using a specific implementation of a Collection is that Hibernate won't honor that as it needs to wrap the collection with a hibernate managed collection.


Regarding businesskeys - then you are correct that it is probably better, but the businesskey just need to be assigned/set on the object (and not change) before adding it to an collection.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 02, 2004 10:28 am 
Newbie

Joined: Wed Dec 01, 2004 10:23 am
Posts: 4
[quote="max"]the only issue with using a specific implementation of a Collection is that Hibernate won't honor that as it needs to wrap the collection with a hibernate managed collection.

Let's use this class as am example:

class C{
private Set items= new ArraySet();
public getItems() {
return items;
}
...
}
Do you mean that even c.getItems return a empty Set, Hibernate still create a Set proxy using another HashSet()? I think Hibernate will only generate Set proxy when lazy="true"?



Are you talking about the wrapper net.sf.hibernate.collection.Set always use HashSet()?
public void beforeInitialize(CollectionPersister persister) {
this.set = persister.hasOrdering() ?
LinkedHashCollectionHelper.createLinkedHashSet() :
new HashSet();
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 02, 2004 10:51 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
i'm talking that to record which items has been removed/deleted from a collection we need to wrap it.

As per the docs - do not assume anything about these Collection/List/Set other than they conform to the Collection API.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 03, 2004 9:23 pm 
Newbie

Joined: Wed Dec 01, 2004 10:23 am
Posts: 4
max wrote:
i'm talking that to record which items has been removed/deleted from a collection we need to wrap it.

As per the docs - do not assume anything about these Collection/List/Set other than they conform to the Collection API.


Thanks for your comments. But I will take the risk and try it in my new project.
If ArrayList really fail, I will hardcode all hashCode() to return 1. :(

After re-read TimTwe's message, instead of saving the hashCode into database, maybe I can save the record create date-time into database? It's much eaiser to ask our DBA to add a CREATE_DATE column. I don't think my DBA will allow me to add HASH_CODE column to database :)
Does anyone have try to use the record create date-time for equal() and hashCode?


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