-->
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.  [ 1 post ] 
Author Message
 Post subject: Problem with hashCode() implementation
PostPosted: Tue Oct 20, 2009 6:14 am 
Newbie

Joined: Fri Aug 14, 2009 8:06 am
Posts: 19
The docs say that to make sure objects from different sessions behave correctly in respect to hashCode() and equals() methods one should override these methods and use hashCode() and equals() on the business keys.

Now this is exactly what I do but I'm running into the following problem:
I have a class that contains a set of items of the same class (class and mapping file included below for clarity). When I load instances of this class I get a NullPointer exception in the hashCode() method because apparently one of the business fields is null. This call however happens because the object is added to the set but is apparently not completely loaded yet.

Is there anyone who has ran into similar problems and found a solution for it? Or does anyone know how to solve this?

The executed code:
Code:
                Session session = HibernateUtil.getSessionFactory().getCurrentSession();

      session.beginTransaction();

      DataItem dataItem = Data.ACCENT.add("test"); // creates and saves a new DataItem

      dataItem.addSubData("subdata 1");
      dataItem.addSubData("subdata 2");

      session.getTransaction().commit();
      
      HibernateUtil.closeSessionFactory();
                HibernateUtil.getSessionFactory();
                session = HibernateUtil.getSessionFactory().getCurrentSession();

      session.beginTransaction();

      List<DataItem> results = session.createQuery("from DataItem").list(); // This line produces the error


The stack trace:
Code:
org.hibernate.PropertyAccessException: Exception occurred inside setter of be.bloso.vetrasoft.model.application.DataItem.allSubData
   at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:89)
   at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:352)
   at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:232)
   at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3580)
   at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:152)
   at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:877)
   at org.hibernate.loader.Loader.doQuery(Loader.java:752)
   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
   at org.hibernate.loader.Loader.doList(Loader.java:2232)
   at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2129)
   at org.hibernate.loader.Loader.list(Loader.java:2124)
   at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)
   at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
   at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
   at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1149)
   at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
   at be.bloso.vetrasoft.model.application.DatabaseTest.testDataItem(DatabaseTest.java:115)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:597)
   at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
   at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
   at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
   at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
   at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
   at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
   at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
   at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
   at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
   at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
   at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
   at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
   at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
   at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
   at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.reflect.InvocationTargetException
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:597)
   at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:66)
   ... 40 more
Caused by: java.lang.NullPointerException
   at be.bloso.vetrasoft.model.application.DataItem.hashCode(DataItem.java:293)
   at java.util.HashMap.put(HashMap.java:372)
   at java.util.HashSet.add(HashSet.java:200)
   at java.util.AbstractCollection.addAll(AbstractCollection.java:305)
   at org.hibernate.collection.PersistentSet.endRead(PersistentSet.java:352)
   at org.hibernate.engine.loading.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:260)
   at org.hibernate.engine.loading.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:245)
   at org.hibernate.engine.loading.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:218)
   at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:900)
   at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:888)
   at org.hibernate.loader.Loader.doQuery(Loader.java:752)
   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
   at org.hibernate.loader.Loader.loadCollection(Loader.java:2019)
   at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:59)
   at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:587)
   at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
   at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1744)
   at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:366)
   at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
   at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)
   at java.util.AbstractCollection.addAll(AbstractCollection.java:303)
   at be.bloso.vetrasoft.model.application.DataItem.setAllSubData(DataItem.java:179)
   ... 45 more


Class source
Code:
public class DataItem implements Comparable<DataItem>, Serializable, DataChangeListener, Lifecycle {
   private static final long serialVersionUID = 1L;

   private Long id;
   private Data rootData; // Data is an Enum
   private DataItem parent;
   private String data;
   private final Set<DataItem> subData = new HashSet<DataItem>();
   private int level;
   private boolean deprecated = false;
        private Integer version;
        private transient boolean isLoaded = false;

   protected DataItem() {
      super(); // Used by Hibernate
   }

   public Long getId() {
      return id;
   }

   protected void setVersion(Integer version) {
      this.version = version;
   }

   protected Integer getVersion() {
      return version;
   }

   public void save() {
      Session session = HibernateUtil.getCurrentSession();

      try {
         if (getId() != null) {
            session.refresh(this);
         }
      }
      catch (HibernateException h) {
         // Object not in db yet
      }

      session.saveOrUpdate(this);

      for (DataItem subDataItem : getAllSubData()) {
         subDataItem.save();
      }
   }

   protected void delete() {
      for (DataItem item : getAllSubData()) {
         item.delete();
      }

      HibernateUtil.getCurrentSession().delete(this);
   }

   protected void setId(Long id) {
      this.id = id;
   }

   public Data getRootData() {
      return rootData;
   }

   protected void setRootData(Data rootData) {
      this.rootData = rootData;
   }

   public void setDeprecated(boolean deprecated) {
      this.deprecated = deprecated;

      if (isLoaded()) {
         for (DataItem item : getAllSubData()) {
            item.setDeprecated(deprecated);
         }
      }
   }

   public boolean isDeprecated() {
      return deprecated;
   }

   public DataItem getParent() {
      return parent;
   }

   protected void setParent(DataItem parent) {
      this.parent = parent;
   }

   public int getLevel() {
      return level;
   }

   protected void setLevel(int level) {
      this.level = level;
   }

   public String getData() {
      return data;
   }

   public void setData(String string) {
      this.data = string;
   }

   @Override
   public String toString() {
      return data;
   }

   public Set<DataItem> getAllSubData() {
      return subData;
   }

   protected void setAllSubData(Set<DataItem> subData) {
      this.subData.addAll(subData);
   }

   public DataItem getSubData(String string) {
      for (DataItem item : getAllSubData()) {
         if (item.toString().equals(string)) {
            return item;
         }
      }

      return null;
   }

   public DataItem getSubData(Long itemId) {
      for (DataItem item : getAllSubData()) {
         if (item.getId().equals(itemId)) {
            return item;
         }
      }

      return null;
   }

   public DataItem removeSubData(String string) {
      DataItem removedItem = getSubData(string);

      getAllSubData().remove(removedItem);
                removedItem.delete();

      save();

      return removedItem;
   }

   public DataItem addSubData(String string) {
      DataItem item = getSubData(string);

      if (item == null) {
         item = new DataItem(this, string);
         subData.add(item);
         item.addDataChangeListener(this);
      }

      return item;
   }

   public boolean hasSubData(String string) {
      return getSubData(string) != null;
   }

   public void clearSubData() {
      for (DataItem item : subData) {
         item.removeDataChangeListener(this);
      }

      subData.clear();
   }

   public int compareTo(DataItem item) {
      if (item.getRootData() != getRootData()) {
         throw new IllegalArgumentException("Can not compare data items from different data sets.");
      }

      return toString().compareTo(item.toString());
   }

   @Override
   public boolean equals(Object object) {
      if (object instanceof DataItem) {
         DataItem item = (DataItem) object;

         return item.getData().equals(getData()) && item.getRootData().equals(getRootData());
      } else {
         return false;
      }
   }

   @Override
   public int hashCode() {
      return getRootData().hashCode() + 29 * getData().hashCode(); // Both getRootData() and getData() are null
   }

   private boolean isLoaded() {
      return isLoaded;
   }

   @Override
   public boolean onDelete(Session session) throws CallbackException {
      return NO_VETO;
   }

   @Override
   public void onLoad(Session session, Serializable serializable) {
      isLoaded = true;
   }

   @Override
   public boolean onSave(Session session) throws CallbackException {
      return NO_VETO;
   }

   @Override
   public boolean onUpdate(Session session) throws CallbackException {
      return NO_VETO;
   }
}


Mapping files (DataItem is a subclass of PersistentObject):
Code:
<hibernate-mapping package="be.bloso.vetrasoft.model">
    <class name="PersistentObject" abstract="true">
      
      <id name="id" column="id">
         <generator class="hilo" />
      </id>
      
      <version name="version" />
    </class>
</hibernate-mapping>

<hibernate-mapping package="be.bloso.vetrasoft.model.application">
   <class name="DataItem" table="DATAITEM">
      
      <id name="id" column="DATAITEM_ID">
         <generator class="hilo" />
      </id>
      
      <version name="version" />

      <property name="rootData" />
      <property name="data"  />
      <property name="level"  />
      <property name="deprecated"  />

      <many-to-one name="parent" class="DataItem" />

      <set name="allSubData" inverse="true" lazy="true" table="DATAITEM">
         <key column="parent" />
         <one-to-many class="DataItem" />
      </set>
   </class>
</hibernate-mapping>


Kind regards,
Stef Kuypers


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

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.