我有一个奇怪的问题,即休眠不会在多对一关系中创建预期的实体类型。我们有以下具有子类层次结构的实体(简化):
@Entity
@Table(name = "A")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 1)
public abstract class A {
@Id
...
public Long getId() { ... }
...
}
@Entity
@DiscriminatorValue("1")
public class A1 extends A {
...
}
@Entity
@DiscriminatorValue("2")
public class A2 extends A {
...
}
@Entity
@Table(name = "B")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 1)
public abstract class B<AClass extends A> {
protected AClass a;
@Id
...
public Long getId() { ... }
...
public abstract AClass getA();
public void setA(AClass a) { ... }
}
@Entity
@DiscriminatorValue("1")
public class B1 extends B<A1> {
...
@Override
@ManyToOne(fetch = EAGER)
@JoinColumn(name = "A_ID")
public A1 getA() { ... }
}
@Entity
@DiscriminatorValue("2")
public class B2 extends B<A2> {
...
@Override
@ManyToOne(fetch = EAGER)
@JoinColumn(name = "A_ID")
public A2 getA() { ... }
}
在persistence.xml
这两个实体中都按顺序声明
A2
A1
B2
B1
现在我在数据库中创建 A1 和 B1 的实例:
A1 a1 = new A1();
entityManager.persist(a1);
B1 b1 = new B1();
b1.setA(a1);
entityManager.persist(b1);
我可以看到实例正确保存到数据库中,每个实例的 ID 为 1,鉴别器也是 1,B 中的 A_ID 也是 1。
当我现在尝试获取 B 时(在另一个休眠会话中):
B b = entityManager.find(B.class, 1L);
我得到了例外:
org.hibernate.PropertyAccessException: Exception occurred inside getter of B
Caused by: java.lang.ClassCastException: A2 cannot be cast to A1
at B1.getA(B1.java:61)
... 108 more
通过调试,我发现 hibernate 正在创建 B1 类型的正确实体,并为与 A 的关系创建了 A2 类型的不正确实体。如果persistence.xml
更改了中的顺序,则会创建正确的 A1 类型。在这种情况下,hibernate 似乎没有考虑 A 表的 DISCRIMINATOR 列,但总是创建配置中声明的第一个子类型。如何解决这个问题?注释有问题吗?
(起初我在超类型 B 中也有方法的具体实现getA()
及其注释,但这会导致类似的问题。)