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.  [ 5 posts ] 
Author Message
 Post subject: Hashcode and Equals on POJO Entities in parent/child setup
PostPosted: Fri Aug 19, 2005 11:35 am 
Regular
Regular

Joined: Wed Dec 17, 2003 1:58 pm
Posts: 102
I'm wondering how exactly I should implement equals() and hashcode() on my objects. Currently I am using the commons HashCodeBuilder and EqualsBuilder for every property on my User/EmailAddress objects. This causes exceptions however when the object is being loaded, due to a circular reference. As the EmailAddress objects are being added to the User, it calls hashcode on EmailAddress, which within its method calls Hashcode on User again.. which throws a Hibernate Exception. I suppose if Hibernate didn't throw the exception I would get a looping hashcode call until everything crashed... any ideas? So am I supposed to leave out all collection type and potentially lazy properties from equals/hashcode? or just not even override equals/hashcode?

Hibernate version:
3.0.5

Mapping documents:
Excerpt from User:
Code:
    <set name="emailAddresses" cascade="all,delete-orphan" lazy="false" fetch="join">
      <key column="USER_ID"/>
      <one-to-many class="org.tecas.model.EmailAddress"/>
    </set>


Excerpt from EmailAddress:
Code:
    <many-to-one name="user" column="USER_ID"/>




Full stack trace of any exception that occurs:
Code:
org.springframework.orm.hibernate3.HibernateSystemException: illegal access to loading collection; nested exception is org.hibernate.LazyInitializationException: illegal access to loading collection
org.hibernate.LazyInitializationException: illegal access to loading collection
   at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:172)
   at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:48)
   at org.hibernate.collection.PersistentSet.hashCode(PersistentSet.java:324)
   at org.apache.commons.lang.builder.HashCodeBuilder.append(HashCodeBuilder.java:348)
   at org.tecas.model.User.hashCode(User.java:108)
   at org.apache.commons.lang.builder.HashCodeBuilder.append(HashCodeBuilder.java:348)
   at org.tecas.model.EmailAddress.hashCode(EmailAddress.java:215)
   at java.util.HashMap.hash(Unknown Source)
   at java.util.HashMap.put(Unknown Source)
   at java.util.HashSet.add(Unknown Source)
   at java.util.AbstractCollection.addAll(Unknown Source)
   at org.hibernate.collection.PersistentSet.endRead(PersistentSet.java:242)
   at org.hibernate.engine.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:183)
   at org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:268)
   at org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:249)
   at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:554)
   at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:541)
   at org.hibernate.loader.Loader.doQuery(Loader.java:436)
   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)
   at org.hibernate.loader.Loader.doList(Loader.java:1593)
   at org.hibernate.loader.Loader.list(Loader.java:1577)
   at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:395)
   at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:271)
   at org.hibernate.impl.SessionImpl.list(SessionImpl.java:844)
   at org.hibernate.impl.QueryImpl.list(QueryImpl.java:74)
   at org.springframework.orm.hibernate3.HibernateTemplate$33.doInHibernate(HibernateTemplate.java:860)
   at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:315)
   at org.springframework.orm.hibernate3.HibernateTemplate.findByNamedQueryAndNamedParam(HibernateTemplate.java:851)
   at org.springframework.orm.hibernate3.HibernateTemplate.findByNamedQueryAndNamedParam(HibernateTemplate.java:841)
   at org.tecas.dao.impl.UserDaoImpl.getUser(UserDaoImpl.java:25)
   at org.tecas.dao.IUserDaoTest.testGetUser(IUserDaoTest.java:26)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at com.intellij.rt.execution.application.AppMain.main(AppMain.java:86)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 19, 2005 12:01 pm 
Expert
Expert

Joined: Wed Apr 06, 2005 5:03 pm
Posts: 273
Location: Salt Lake City, Utah, USA
Short answer: don't put emailAddresses in the User's equals/hashcode.

Long answer: Typically you won't put inverse relationships in equals/hashcode - meaning you won't put email addresses in the users equals/hashcode. You only want to include defining attributes, and the email addresses a user has doesn't define the user. On the other hand, it makes more sense to have an email address be defined by its user.

Picking attributes to include in equals/hashcode is a difficult process. If you don't expect to be placing your objects in hash maps or anything, you might consider not overriding equals/hashcode. Otherwise, you want to pick only attributes that define the object - and should never change. Where possible, I like to enforce this on my objects by making users of my objects call a non-default constructor that takes all the defining attributes, and hiding the setters for those attributes so they can't be changed once the object is created.

Here's a good (long) reader that shows some of the potential pitfalls of equals/hashcode and persistent objects: http://forum.hibernate.org/viewtopic.php?t=928172


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 19, 2005 12:06 pm 
Regular
Regular

Joined: Wed Dec 17, 2003 1:58 pm
Posts: 102
What is your take on properties that may be lazy, (individual properties or collections)? I have different areas of my app where it may or may not be loaded.. which leads to errors when calling hashcode on that property. And i feel these lazy properties are defining to the containing class.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 19, 2005 12:11 pm 
Expert
Expert

Joined: Wed Apr 06, 2005 5:03 pm
Posts: 273
Location: Salt Lake City, Utah, USA
You should be fine using lazy associations in equals/hashcode - assuming the object is still attached to an open session when equals/hashcode gets called for the first time. Just like with everything else, you have to make sure you initialize your object properly before making it detached.

I think the error you posted originally was related to the circular reference, not the lazy loading.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 19, 2005 12:18 pm 
Regular
Regular

Joined: Wed Dec 17, 2003 1:58 pm
Posts: 102
Ya I have a difficult situation because i immediaetly detach my object(s) as soon as they are loaded, so I was thinking I might be able to check if an object is a proxy in my eq/hc method before checking its equality/hc, however that just causes more problems and won't guarantee anything: ie if i had 2 objects that were exactly the same, but one of them had a set proxied, hc/eq would end up being different even though they were the same object. So I suppose I just won't use eq/hc, and be very careful in my coding =)


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