【问题标题】:Strange JPA one-to-many behavior when trying to set the "many" on the "one" entity尝试在“一”实体上设置“多”时出现奇怪的 JPA 一对多行为
【发布时间】:2010-06-15 10:50:03
【问题描述】:

我已经使用 JPA(特别是 Hibernate)映射了两个实体。这些实体具有一对多的关系(我已经简化了演示):

@Entity
public class A {

    @ManyToOne
    public B getB() { return b; }
}

@Entity
public Class B {

    @OneToMany(mappedBy="b")
    public Set<A> getAs() { return as; }
}

现在,我正在尝试通过使用关系的一侧/非所有者侧(即被引用的表)的设置器在这些实体的两个实例之间创建关系:

em.getTransaction().begin();

A a = new A();
B b = new B();
Set<A> as = new HashSet<A>();
as.add(a);
b.setAs(as);

em.persist(a);
em.persist(b);
em.getTransaction().commit();

但是,这种关系不会持续到数据库中(为实体 A 创建的行没有引用为实体 B 创建的行)。为什么会这样?我希望它能够工作。

此外,如果我从 @OneToMany 注释中删除“mappedBy”属性,它工作。再次 - 为什么会这样?以及删除“mappedBy”属性可能产生的影响是什么?

【问题讨论】:

    标签: hibernate jpa entity-relationship


    【解决方案1】:

    在双向关联中,JPA 规范是这样定义的,当它想要查看关联的当前“状态”以确定需要持久化的内容时,实现只查看关联的拥有方,并且每个双向关联都具有拥有和反面。这可以避免歧义(即,如果关联的双方不一致,要坚持什么?),并为 JPA 实现者中的优化和更简单的实现提供机会。请注意,这通常不是问题,因为双向关联应该由您正确维护,而不是由 JPA。当您始终在应用程序中正确维护双向关联(更新双方并保持一致)时,就没有问题。

    带有 mappedBy 的 OneToMany 是相反的一面,因此 JPA impl 在确定刷新/事务提交的关联状态时不会查看这一面。它只查看 A.getB() 并且 this 为 null,因此 JPA 的关联为 null。

    没有 mappedBy 的 OneToMany,因此它成为拥有方,仅自 JPA 2.0 起才受支持,但我认为 Hibernate 自古以来就支持它。如果您从 OneToMany 中删除 mappedBy,这就是您的示例有效的原因。在这种情况下,OneToMany 成为拥有方,因此实现“查看”这一方以确定要保留的内容。 这不会改变您的内存关联仍然不完整的事实。你应该设置两边。

    更新:我不知道 Hibernate 在您从任何一方离开 mappedBy 时会做什么,但我认为这可能会导致不太理想的 SQL。另见:http://simoes.org/docs/hibernate-2.1/155.html,尤其是关于“inverse="false"”的部分。 “逆”是 JPA“mappedBy”的本地 Hibernate 术语。也就是说,Hibernate 映射中的 inverse="true" 与在 JPA 映射中使用 mappedBy="other" 相同,都将这一侧标记为确定关联更新时忽略的反向侧。

    【讨论】:

    • 感谢您的详细解答。如果没有“mappedBy”,如果我更改“多”侧(A),他也会保留数据,所以我猜它同时查看(或者它可能只是休眠?)。毫无疑问,你应该管理你身边的关系(在记忆中),但有时你只想保持“一个”方面而不关心它的“许多”实体是否正确设置在记忆中(引用他)。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    • 2020-02-10
    • 2011-03-28
    • 2021-12-22
    • 1970-01-01
    相关资源
    最近更新 更多