2

I have two objects

  • One by lazy loaded

      product:5757b95d1d8eecdd01e59b29$LazyLoadingProxy
    
  • The other eager loaded

      com.entity.Product@5e6c4568
    

I know both objects are the same since they have the same unique id (id=5757b95d1d8eecdd01e59b29).

I have in my Product class following methods:

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = (prime * result) + ((id == null) ? 0 : id.hashCode());
    return result;
  }

  @Override
  public boolean equals(final Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    final Item other = (Item) obj;
    if (id == null) {
      if (other.id != null) {
        return false;
      }
    } else if (!id.equals(other.id)) {
      return false;
    }
    return true;
  }

But now when I do the following operation I get no match. Any clues ?

temp.contains(product) == false

temp contains the lazy loaded items and product contains normal items.

mp911de
  • 17,546
  • 2
  • 55
  • 95
Saurabh Kumar
  • 16,353
  • 49
  • 133
  • 212
  • Hint: Your `equals` method casts `obj` to `Item`. It's either a bug or not obvious that `Product extends Item`. – mp911de Jun 09 '16 at 09:18

1 Answers1

1

In short

It's the way how you implemented equals.

Explanation

Spring Data MongoDB creates lazy-loading proxies using code-generation libraries. The class of the lazy-loaded reference at runtime would be something like com.example.Product$$EnhancerByCGLIB$$5f3cdccd. Your implementation performs a check of the exact class type

if (getClass() != obj.getClass()) {
  return false;
}

that causes equals to return false. A more friendly version of the check is:

if (!(o instanceof Product)) {
    return false;
}

Please also be aware that depending on which instance is in the collection and which is passed to contains() the equals and hashCode methods are called either on the proxy instance or the entity class. That is is not relevant for the id check as the id field is always populated but it would get relevant if you tried to compare other properties. The reason behind is the proxy fields are not initialized (and won't be initialized) as the resolved object is held separate. That means comparing properties other than id require calls to their getters.

mp911de
  • 17,546
  • 2
  • 55
  • 95