gpt4 book ai didi

java - Hibernate 在关系中创建错误的实体子类型

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:46:28 24 4
gpt4 key购买 nike

我有一个奇怪的问题,即 hibernate 不会在多对一关系中创建预期的实体类型。我们有以下具有子类层次结构的实体(简化):

@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,DISCRIMINATOR 也是 1,B 中的 A_ID 也是 1。

当我现在尝试获取 B 时(在另一个 hibernate session 中):

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 列,但总是创建配置中声明的第一个子类型。这怎么能解决?注释有问题吗?

(我最初也有方法getA()的具体实现,它在父类(super class)型B中有注解,但这会导致类似的问题。)

最佳答案

借助 Hibernate 5.0.2.Final,我能够使用 @ManyToOne(..., targetEntity = A.class) 使您的示例正常工作。我还将 public abstract AClass getA(); 替换为普通的 getter。

@Entity
@Table(name = "B")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 1)
public abstract class B<AClass extends A> {
private Long id;
private AClass a;

@Id
@GeneratedValue
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

@ManyToOne(fetch = FetchType.EAGER, targetEntity = A.class)
@JoinColumn(name = "A_ID")
public AClass getA() {
return a;
}

public void setA(AClass a) {
this.a = a;
}
}
@Entity
@DiscriminatorValue("1")
public class B1 extends B<A1> {
// no need to override getA()
}
@Entity
@DiscriminatorValue("2")
public class B2 extends B<A2> {
// no need to override getA()
}

我没有在文档中找到有关此行为的任何信息。所以我只有我的观察:

  • 没有 targetEntity = A.class 当急切地从 获取行时,Hibernate 甚至没有查询表 ADISCRIMINATOR 列AB,就像它已经决定了 A 的实际类型一样。
  • 当我添加 targetEntity = A.class 时,A.DISCRIMINATOR 出现在查询中,并且使用类 A 的正确子类创建了对象

关于java - Hibernate 在关系中创建错误的实体子类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32829560/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com