gpt4 book ai didi

java - JPA继承问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:29:04 25 4
gpt4 key购买 nike

使用 JPA 1(hibernate-core 版本 3.3.0.SP1 和 hibernate-entitymanager 版本 3.4.0.GA):我有一些类似于下面定义的实体,其中 ChildOne 和 ChildTwo 从 Father 实体扩展而来。

@Entity
@Table(name = "TABLE_FATHER")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.INTEGER, name = Father.C_ID_CTG)
public class Father {

@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "sq")
@Column(name = "ID_PK", nullable = false)
@BusinessId
private Long id;
...
}

@Entity
@Table(name = "TABLE_CHILD_ONE")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorValue(Categories.ID_CTG_ONE)
public class ChildOne extends Father {
...
}

@Entity
@Table(name = "TABLE_CHILD_TWO")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorValue(Categories.ID_CTG_TWO)
public class ChildTwo extends Element {
...
}

假设我有一个实体有一个父元素,另一个实体有一组父元素。在这两种情况下,都应该去子实体。

@Entity
@Table(name = "TABLE_ONE")
public class OneTable {

@JoinColumn(name = "ID_PK", referencedColumnName = "ID_PK", nullable = false)
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Father element;
...
}

@Entity
@Table(name = "TABLE_ANOTHER")
public class Another {

@Fetch(FetchMode.JOIN)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "id", fetch = FetchType.LAZY)
private Collection<Father> elementCollection;

...
}

我期望始终获取子元素,但是当我获取元素时 getElement() 返回父元素另一方面,当我获取集合 getElementCollection() 时,子元素就来了。

显然,@JoinColumn 是导致此行为的原因,它与父表进行连接并忘记了子元素。该集合按预期工作。

如何通过 getElement() 调用获取子元素?任何想法或解决方法?提前致谢。

最佳答案

问题不是由@JoinColumn引起的。原因是延迟加载。我设法在更简单的例子中查明了你的问题。请原谅我将惯例从父亲改为 parent 。

在下面的示例中,未初始化的元素是 jpa.inheritance.issue.Parent_$$_javassist_1 的类型。它是一个 Hibernate Proxy - 动态创建的 Parent 子类。您可以通过调用 Hibernate 专有 API getHibernateLazyInitializer().getImplementation() 来“解除代理”。

elementCollection 的集合也是延迟初始化的。集合的类型是 org.hibernate.collection.PersistentBag,它在第一次访问时使用正确的数据进行初始化。集合被一次性初始化。请查看使用您的确切 Hibernate 版本 (3.3.0.SP1/3.4.0.GA) 成功通过绿色测试的测试。

    @Test
public void test() {
Child c = new Child();
em.persist(c);

Another a = new Another();
a.setElement(c);
Collection<Parent> col = new ArrayList<Parent>();
col.add(c);
a.setElementCollection(col);
em.persist(a);
c.setAnother(a);

long idx = a.getId();
tx.commit();

// I'm cleaning the cache to be sure that call to a.getElement() will return proxy.
em.clear();
tx = em.getTransaction();
tx.begin();

a = em.find(Another.class, idx);
Assert.assertNotNull(a);
Parent p = a.getElement();
// At this point p is a type of jpa.inheritance.issue.Parent_$$_javassist_1

Assert.assertTrue(p instanceof Parent);
Assert.assertFalse(p instanceof Child);

// At this point a.elements is a not initialized (empty) collection of type org.hibernate.collection.PersistentBag
// When we access this collection for the first time, records are read from the database
Assert.assertEquals(1, a.getElementCollection().size());

if (p instanceof HibernateProxy) {
p =
(Parent) ((HibernateProxy) p).getHibernateLazyInitializer()
.getImplementation();
}

// At this point p is a type of jpa.inheritance.issue.Child
Assert.assertTrue(p instanceof Child);
}

@Entity
public class Another {

@JoinColumn(name = "element_id", referencedColumnName = "id", nullable = false)
@ManyToOne(fetch=FetchType.LAZY)
private Parent element;
public Parent getElement() {
return element;
}

public void setElement(Parent element) {
this.element = element;
}

@OneToMany(cascade = CascadeType.ALL, mappedBy = "another", fetch = FetchType.LAZY)
public Collection<Parent> elements;

public Collection<Parent> getElementCollection() {
return elements;
}

public void setElementCollection(Collection<Parent> elementCollection) {
this.elements = elementCollection;
}

// @Id ...
}

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Parent {
@ManyToOne
private Another another;

public Another getAnother() {
return another;
}

public void setAnother(Another another) {
this.another = another;
}

// @Id ...
}

@Entity
public class Child extends Parent {
}

您不需要 @DiscriminatorColumn 也不需要 @DiscriminatorValue,因为需要这些注解和 InheritanceType.SINGLE_TABLE 作为确定类型。使用 InheritanceType.JOINED,Hibernate 能够通过检查两个(父表和子表)表中是否存在具有相同 ID 的记录来确定多态类型。您可以打开 hibernate 日志记录以查看确定类型的查询是什么样子的。它是这样工作的:

select
another0_.id as id0_1_,
another0_.element_id as element2_0_1_,
parent1_.id as id1_0_,
parent1_1_.name as name2_0_,
case
when parent1_1_.id is not null then 1
when parent1_.id is not null then 0
else -1
end as clazz_0_
from
Another another0_
inner join
Parent parent1_
on another0_.element_id=parent1_.id
left outer join
Child parent1_1_
on parent1_.id=parent1_1_.id
where
another0_.id=?

关于java - JPA继承问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24552319/

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