Posts Tagged ‘equals’

Some approach for writing equials() and hashCode()

Monday, March 24th, 2008

The problem described in details in http://www.hibernate.org/109.html
The problem is that if we implement equals()/hashCode() as comparison and hashCode() of entity’s ids (see http://djeang.blogspot.com/2005/08/override-equals-and-hashcode-methods.html) then the hashCode() (and, possibly, equals()) will change after saving entities if ids are generated by DB.
To solve this issue I can suggest to use inner classes with equals()/hashCode(). It will not affect Hibernate’s internal collections taskflow, but will allow you to use ids in equals()/hashCode() after entities are persisted. On other hand hashCode() and equals() will not change in your persistent objects after you have saved it.

public class Test3 {
   static class SomeEntity {
       private Integer id;   

       private String data;   

       public SomeEntity() {
           super();
       }   

       public SomeEntity(Integer id, String data) {
           super();
           this.id = id;
           this.data = data;
       }   

       public Integer getId() {
           return id;
       }   

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

       public String getData() {
           return data;
       }   

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

       public class SomeEntityId {
           private SomeEntity link = null;   

           public SomeEntityId(SomeEntity link) {
               super();
               this.link = link;
           }   

           @Override
           public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if ((obj == null) || (obj.getClass() != this.getClass()))
   return false;
  if (this.link.getClass() != ((SomeEntityId) obj).getLink().getClass())
   return false;   

               Integer thisId = link.getId();
               Integer otherId = ((SomeEntityId) obj).getLink().getId();
               if ((thisId == null) || (otherId == null))
                   throw new RuntimeException("Id not defined!");   

               return thisId.equals(otherId);
           }   

           @Override
           public int hashCode() {
               Integer thisId = link.getId();
               if (thisId == null)
                   throw new RuntimeException("Id not defined!");   

               return thisId.hashCode();
           }   

           public SomeEntity getLink() {
               return link;
           }
       };   

       public SomeEntityId getDTO() {
           return new SomeEntityId(this);
       }
   }   

   public static void main(String[] args) {
       SomeEntity e0 = new SomeEntity(null, "no id");
       SomeEntity e1 = new SomeEntity(1, "e1");
       SomeEntity e2 = new SomeEntity(2, "e2");
       SomeEntity e3 = new SomeEntity(3, "e3");
       SomeEntity e33 = new SomeEntity(3, "e33");   

       Set aSet = new HashSet();
       // aSet.add(e0.getDTO());
       aSet.add(e1.getDTO());
       aSet.add(e2.getDTO());
       aSet.add(e3.getDTO());
       aSet.add(e33.getDTO());   

       System.out.println(”set size: ” + aSet.size());
       System.out.println(”set:”);
       for (SomeEntity.SomeEntityId seId : aSet) {
           SomeEntity se = seId.getLink();
           System.out.println(”entity: ” + se.getData());
       }
   }
}

I even could suggest you to add it to entities code generation in such tools as Hibernate Tools.
I would also like to mention also that SomeEntityId object could be stored in transient field of an entity.
Comments are welcome.