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.