Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you get equals() working with Hibernate entities when lazy=true?

For some reason when lazy=true on all my entities, the equals() method does not work correctly when one side is a lazily-loaded entity and the other side is a normal entity. Here's an example:

if(activeTask.getTask().equals(task)) {...}

In this case, the activeTask's task will be a proxy while the right side will be a regular one. The equals() will fail. To fix this problem, I often do things like this:

if(activeTask.getTask().getId() == task.getId()) {...}

This works, but it's not ideal. I'd rather use my equals() method.

Does anyone have a nice solution to this problem? It really adds to the application's level of noise to have to think about stuff like this.

If I say lazy=false, I don't have to deal with proxy's, and so equals() will work. But this has a very negative impact on performance.

It is just not cool to have to say, "equals() works in all cases, except when you use proxies... then equals() is not reliable."

like image 382
egervari Avatar asked Nov 29 '10 23:11

egervari


People also ask

How does Hibernate lazy loading work?

Hibernate now can "lazy-load" the children, which means that it does not actually load all the children when loading the parent. Instead, it loads them when requested to do so. You can either request this explicitly or, and this is far more common, hibernate will load them automatically when you try to access a child.

How does lazy loading work 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.

How do you load a lazy object in Hibernate?

To enable lazy loading explicitly you must use “fetch = FetchType. LAZY” on an association that you want to lazy load when you are using hibernate annotations. @OneToMany( mappedBy = "category", fetch = FetchType.

What is the difference between lazy and eager loading in Hibernate?

Eager Loading is a design pattern in which data initialization occurs on the spot. Lazy Loading is a design pattern that we use to defer initialization of an object as long as it's possible.


1 Answers

I realize this is an old question, but it's still unanswered and people might stumble upon it.

I had the same problem a few days ago. In the project we use an abstract base class BasicEntityType, which has just an ID and equals is implemented in said base class:

@Override
public final boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }

    if (obj == null) {
        return false;
    }

    Class<?> objClass = HibernateProxyHelper.getClassWithoutInitializingProxy(obj);
    if (this.getClass() != objClass) {
        return false;
    }

    if (id == null) {
        return false;
    }

    return id.equals(((BasicEntityType) obj).getId());
}

There are two critical parts in this code:

  • First: Do not check directly for class equality, it might not work with the given object.
  • Second: All properties of the given object have to be accessed by using methods. Or you could unwrap the actual object.
like image 62
Tangresh Avatar answered Sep 18 '22 15:09

Tangresh