Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate/JPA equals() and hashCode() with Lazy loaded Business Identifier

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.

like image 232
Dominik Obermaier Avatar asked Jun 08 '11 21:06

Dominik Obermaier


People also ask

In what cases equals () and hashCode () should be overridden when using hibernate?

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).

Do JPA entities need equals and hashCode?

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.

What is lazy loading in JPA?

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.


2 Answers

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;
    }
}
like image 101
Marcin Michalski Avatar answered Oct 13 '22 23:10

Marcin Michalski


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.

like image 36
Marcelo Avatar answered Oct 13 '22 22:10

Marcelo