Some approach for writing equials() and hashCode()

The problem described in details in The problem is that if we implement equals()/hashCode() as comparison and hashCode() of entity’s ids (see 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(); = id; = data; } public Integer getId() { return id; } public void setId(Integer id) { = id; } public String getData() { return data; } public void setData(String data) { = data; } public class SomeEntityId { private SomeEntity link = null; public SomeEntityId(SomeEntity link) { super(); = link; } @Override public boolean equals(Object obj) { if (this == obj) return true; if ((obj == null) || (obj.getClass() != this.getClass())) return false; if ( != ((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.