Defining object equality by primary key
Consider the following code:
package session1; ... public class LoadUser { ... final User user; { final Session session = HibernateUtil.createSessionFactory("session1/hibernate.cfg.xml").openSession(); final Transaction transaction = session.beginTransaction(); user = (User) session.load(User.class, 1L); final User user1 = (User) session.load(User.class, 1L); System.out.println("first transaction: user.equals(user1):" + user.equals(user1)); ❶ transaction.commit(); session.close(); } { final Session session = HibernateUtil.createSessionFactory("session1/hibernate.cfg.xml").openSession(); final Transaction transaction = session.beginTransaction(); final User user2 = (User) session.load(User.class, 1L); System.out.println("second transaction: user.equals(user2):" + user.equals(user2)); ❷ transaction.commit(); session.close(); } ...
At first we compare two session1.User
instances being read by the same session manager ❶. Subsequently we compare a detached
session1.User
instance with a second instance
being read by a different session ❷. This yields the following
result:
first transaction: user.equals(user1):true ❶ second transaction: user.equals(user2):false ❷
The two instances in question definitely represent the same database entity. The two entity managers referring to different sessions create two distinct instances within a given Java™ runtime.
Since JPA entities require an
@javax.persistence.Id
attribute we may generally define
object equality solely based on this at tribute's value:
package session2; ... public class User { @Id @GeneratedValue private Long id; ... @Override public boolean equals(Object other) { if (this == other) ❶{ return true; } else if (other instanceof User) { return getId().equals(((User) other).getId()) ❷; } else { return false; } } @Override public int hashCode() { ❸ if (null == id) { return System.identityHashCode(this); } else { return getId().hashCode(); } } }
This way of defining
session2.User.equals(java.lang.Object)
implies that either or both of the following two conditions must be
met:
Both instances must be identical. |
|
Both instances must have the same
|
Caution
Do not forget to implement
Object.hashCode()
❸
accordingly: Two instances a
and b
returning a.equals(b) == true
equal must return an
identical hash code value a.hashCode() ==
b.hashCode()
in order to satisfy a collection's
contract.
[Bloch2008] covers the contract of
Object.hashCode()
and its close relation
to Object.equals(Object)
in
detail.