尝试在"一个"实体上设置"多个"时,奇怪的JPA一对多行为

Eya*_*oth 1 entity-relationship hibernate jpa

我使用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; }
}
Run Code Online (Sandbox Code Playgroud)

现在,我试图通过使用关系的单侧/非所有者侧的setter(即被引用的表)来创建这些实体的两个实例之间的关系:

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();
Run Code Online (Sandbox Code Playgroud)

但是,关系不会持久保存到DB(为实体A创建的行不引用为实体B创建的行).为什么会这样?我希望它能起作用.

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

rom*_*anb 5

在双向关联中,JPA规范被定义为当实现仅想查看关联的当前"状态"以确定需要持久化并且每个双向关联具有拥有权和反面.这可以避免歧义(即,如果关联的两边不一致会持续什么?)以及为JPA实现者提供优化和更简单实现的机会.请注意,这通常不是问题,因为您应该正确维护双向关联,而不是JPA.如果始终在应用程序中正确维护双向关联(更新双方并保持一致),则没有问题.

具有mappedBy的OneToMany是反面,因此在确定刷新/事务提交上的关联状态时,JPA impl不会查看此方.它只查看A.getB()并且它为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""的部分."inverse"是JPA"mappedBy"的原生Hibernate术语.也就是说,Hibernate映射中的inverse ="true"与在JPA映射中使用mappedBy ="other"相同,都将此侧标记为在确定关联更新时被忽略的反面.