Artem's blog

March 24, 2008

Some approach for writing equials() and hashCode()

Filed under: Software — Tags: , , , , , — Artem @ 3:40 AM

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.

 
 

You need to log in to vote

The blog owner requires users to be logged in to be able to vote for this post.

Alternatively, if you do not have an account yet you can create one here.

Powered by Vote It Up

Powered by WordPress