I'm wondering how to write a correct equals() and hashCode() for Hibernate Entities which have a Lazy Loaded ManyToOne relation to another Entity which is important as a business key. Note, that I already read the Hibernate documentation on this topic and I know I must/should not use the object id.
To clarify, here an example:
public class BusinessEntity implements Serializable
{
//for simplicity, here just the important part
private String s;
@ManyToOne(fetch= FetchType.LAZY )
private ImportantEntity anotherEntity;
@Override
public boolean equals( Object obj )
{
//Here I would like to call something like
// (obj.getAnotherEntity.getName.equals(getAnotherEntity.getName) && obj.getS().equals(getS());
return true;
}
}
Of course this is just a simplified example. But I hope I could explain my scenario. Has someone tried something like that before? I did not find anything regarding to this topic.
You only need to override equals() and hashcode() if the entity will be used in a Set (which is very common) AND the entity will be detached from, and subsequently re-attached to, hibernate sessions (which is an uncommon usage of hibernate).
Introduction. As previously explained, using the JPA entity business key for equals and hashCode is always best choice. However, not all entities feature a unique business key, so we need to use another database column that is also unique, as the primary key.
lazy it is interpreted as a hint to the jpa provider that the loading of that field may be delayed until it is accessed for the first time: the property value in case of a @basic annotation, the reference in case of a @manytoone or a @onetoone annotation, or.
For simplicity I have skipped null-safety code. But the idea is to create additional property which will persist entity name and will not expose it to the outside world
public class BusinessEntity implements Serializable
{
//for simplicity, here just the important part
private String s;
@ManyToOne(fetch= FetchType.LAZY )
private ImportantEntity anotherEntity;
private String anotherEntityName;
@Override
public boolean equals( Object obj )
{
if(BusinessEntity.class.isAssignableFrom(obj.getClasS())){
BusinessEntity other = (BusinessEntity)obj;
return other.anotherEntityName.
equals(this.anotherEntityName) &&
other.s.equals(this.s);
}
return true;
}
public void setAnotherEntity(ImportantEntity ie){
anotherEntityName= ie.getName();
anotherEntity = ie;
}
}
In the equals you should use instanceof to compare types and the getters of the properties that you need to include.
instanceof is used because of the proxy classes that hibernate uses and the getters are used to enable lazy loads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With