I have a problem with lazy loading in hibernate when dealing with inheritance. I have one entity that references a second entity that is subclassed. I want the reference to load lazily, but this causes errors in my .equals() methods.
In the code below, if you call equals() on an instance of A, the check fails in the C.equals() function when checking if the Object o is an instance of C. It fails because the other object is actually a Hibernate proxy created by javassist, which extends B, not C.
I understand that Hibernate cannot create a proxy of type C without going to the database and thus breaking the lazy loading. Is there a way to make the getB() function in class A return the concrete B instance instead of the proxy (lazily)? I've tried using the Hibernate specific @LazyToOne(LazyToOneOption.NO_PROXY) annotation on the getB() method to no avail.
@Entity @Table(name="a")
public class A {
private B b;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="b")
public B getB() {
return this.b;
}
public boolean equals(final Object o) {
if (o == null) {
return false;
}
if (!(o instanceof A)) {
return false;
}
final A other = (A) o;
return this.getB().equals(o.getB());
}
}
@Entity @Table(name="b")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="type",
discriminatorType=DiscriminatorType.STRING
)
public abstract class B {
private long id;
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof B)) {
return false;
}
final B b = (B) o;
return this.getId().equals(b.getId());
}
}
@Entity @DiscriminatorValue("c")
public class C extends B {
private String s;
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (obj == null) {
return false;
}
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof C)) {
return false;
}
final C other = (C) o;
if (this.getS() == null) {
if (other.getS() != null) {
return false;
}
} else if (!this.getS().equals(other.getS())) {
return false;
}
return true;
}
}
@Entity @DiscriminatorValue("d")
public class D extends B {
// Other implementation of B
}