在处理继承时,我在hibernate中有延迟加载的问题。我有一个实体引用了子类的第二个实体。我希望引用延迟加载,但这会导致我的.equals()方法出错。
在下面的代码中,如果在A的实例上调用equals(),则在检查Object o是否为C的实例时,检查在C.equals()函数中失败。它失败,因为另一个对象是实际上是由javassist创建的Hibernate代理,它扩展了B,而不是C。
据我所知,Hibernate无法在不进入数据库的情况下创建C类代理,从而打破了延迟加载。有没有办法让类A中的getB()函数返回具体的B实例而不是代理(懒惰)?我尝试在getB()方法上使用Hibernate特定的@LazyToOne(LazyToOneOption.NO_PROXY)注释无效。
@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
}
答案 0 :(得分:1)
事实证明,我正在尝试使用@LazyToOne(LazyToOneOption.NO_PROXY)注释进行正确的跟踪。这对我来说不起作用,因为我还没有运行Hibernate字节码增强工具。有关这方面的说明,请访问:
答案 1 :(得分:0)
您可能想尝试将getB()上的fetch
属性更改为FetchType.EAGER
。希望这会有所帮助。
答案 2 :(得分:0)
无论对象是实体还是/或延迟加载,实际上都不可能尊重equals的契约,并且在使用instanceof的子类中具有equals的特化。实际上,您将处于b1.equals(c1) == true
但c1.equals(b1) == false
的情况。
所以,我认为超类(B)应该定义equals,并使其成为final,因为所有子类都应该使用基类equals
方法。
那就是说,你在B中的等于方法是不对的:
if (!super.equals(obj)) {
return false;
}
这意味着equals的Object实现必须返回true才能使两个B实例相等。这意味着如果两个B实例是同一个对象,它们只是等于。
if (!(obj instanceof C)) {
return false;
}
为什么B类检查另一个实例是否是C的实例。它应该检查另一个实例是否是B的实例。
最后,如果它们具有相同的ID,则两个B是相等的,并且因为所有继承树的ID必须是唯一的,所以如果你使这个等于方法最终,那么你是安全的。