Ultimate Guide To Implementing Equals and Hashcode With Hibernate
Ultimate Guide To Implementing Equals and Hashcode With Hibernate
www.thoughts-on-java.org
Implementing equals() and hashCode()
@Entity
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NaturalId
private String businessKey;
private MyEntity() {}
@Override
public int hashCode() {
return Objects.hashCode(businessKey);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyEntity other = (MyEntity) obj;
return Objects.equals(businessKey, other.getBusinessKey());
}
}
www.thoughts-on-java.org
Implementing equals() and hashCode()
Please note that the only public constructor of the MyEntity class
requires a value for the businessKey attribute. The no-args
constructor is private. This is a Hibernate-specific implementation
that’s not supported by the JPA specification. It ensures that the
businessKey attribute is always set and that the hash code of the
object will not change.
If you want to implement this in a JPA-compliant way, you need to
provide a public, no-args constructor. You then need to accept that
the hash code of the object changes when you set the businessKey
attribute or you need to use a fixed hash code as I do for generated
primary key values. In general, a changed hash code doesn’t create
any problems as long as you set the value of the businessKey
attribute before you add the entity object to any Set.
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NaturalId
private String businessKey;
@ManyToOne
private MyParent parent;
private MyEntity() {}
@Override
public int hashCode() {
return Objects.hash(parent, businessKey);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyEntity other = (MyEntity) obj;
return Objects.equals(parent, other.getParent())
&& Objects.equals(businessKey, other.getBusinessKey());
}
}
www.thoughts-on-java.org
Implementing equals() and hashCode()
here is that you set the primary key value in the constructor or
immediately after you instantiated a new entity object.
@Entity
public class MyEntity {
@Id
private Long id;
private MyEntity() {}
@Override
public int hashCode() {
return Objects.hashCode(id);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyEntity other = (MyEntity) obj;
return Objects.equals(id, other.getId());
}
}
www.thoughts-on-java.org
Implementing equals() and hashCode()
Using a Generated Primary Key
As I teased earlier, generated primary keys create a problem for the
implementation of your equals() and hashCode() methods. That’s
because the primary key value gets set when the entity gets
persisted. So, your entity object can exist with and without a primary
key value.
The challenge here is that the hash code of your entity isn’t allowed
to change after you added the object to a Set. So, you can’t use the
primary key to calculate the hash code. You need to return a fixed
value that’s the same for all objects of the entity class. That, of
course, negatively affects the performance of very huge Sets and
Maps because they put all objects into the same hash bucket. But
Hibernate can’t efficiently manage huge associations anyways and
you should avoid them in general.
@Entity
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Override
public int hashCode() {
return 13;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyEntity other = (MyEntity) obj;
return id != null && id.equals(other.getId());
www.thoughts-on-java.org
Implementing equals() and hashCode()
if (getClass() != obj.getClass())
return false;
MyEntity other = (MyEntity) obj;
return id != null && id.equals(other.getId());
}
}
www.thoughts-on-java.org