尝试设置“多"链接时,奇怪的JPA一对多行为.在“一个"上实体 [英] Strange JPA one-to-many behavior when trying to set the "many" on the "one" entity

查看:77
本文介绍了尝试设置“多"链接时,奇怪的JPA一对多行为.在“一个"上实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用JPA(特别是Hibernate)映射了两个实体.这些实体之间存在一对多的关系(我已经简化了介绍):

I've mapped two entities using JPA (specifically Hibernate). Those entities have a one-to-many relationship (I've simplified for presentation):

@Entity
public class A {

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

@Entity
public Class B {

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

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

Now, I'm trying to create a relationship between two instances of these entities by using the setter of the one-side/not-owner-side of the relationship (i.e the table being referenced to):

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创建的行).为什么会这样呢?我希望它能正常工作.

But then, the relationship isn't persisted to the DB (the row created for entity A isn't referencing the row created for entity B). Why is it so? I'd excpect it to work.

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

Also, if I remove the "mappedBy" property from the @OneToMany annotation it will work. Again - why is it so? and what are the possible effects for removing the "mappedBy" property?

推荐答案

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

In bidirectional associations the JPA spec is defined such that the implementation only looks at the owning side of the association when it wants to see the current "state" of the association to determine what needs to be persisted and each bidirectional association has both an owning and an inverse side. This can avoid ambiguities (i.e. what to persist if both sides of the association are not consistent?) as well as give opportunities for optimizations and simpler implementations in the JPA implementors. Note that this is generally not a problem, because bidirectional associations should be maintained properly by you, not by JPA. When you always maintain bidirectional associations properly in your application (updating both sides and keeping them consistent), there is no problem.

OneToMany是反面,因此,在确定刷新/事务提交时的关联状态时,JPA impl不会查看该面.它只会查看A.getB(),并且为null,因此对于JPA,关联为null.

OneToMany with mappedBy is an inverse side, hence the JPA impl does not look at this side when determining the state of the association on flush/transaction commit. It only looks at A.getB() and this is null, so the association is null for JPA.

不具有mappingBy的OneToMany,因此成为拥有者,仅从JPA 2.0开始才受支持,但我认为Hibernate从很久以前就支持它.这就是为什么如果您从OneToMany中删除mapledBy,则示例可以工作的原因.在那种情况下,OneToMany成为拥有方,因此实现查看"这一方以确定要保留的内容. 这不会改变您的内存中关联仍然不完整的事实.您应该同时设置两侧.

OneToMany without mappedBy, so that is becomes the owning side, is only supported since JPA 2.0 but I think Hibernate supports it since ages. Thats why your example works if you remove mappedBy from OneToMany. In that case the OneToMany becomes the owning side and hence the implementation "looks at" this side to determine what to persist. This does not change the fact that your in-memory association is still incomplete. You should set both sides.

更新:当您从任一侧离开mapdBy时,我不完全知道Hibernate会做什么,但是我认为这可能会导致最佳SQL降低.另请参阅: http://simoes.org/docs/hibernate-2.1/155.html ,尤其是有关"inverse ="false"的部分. "inverse"是JPA"mappedBy"的本地Hibernate术语.也就是说,在Hibernate映射中,inverse ="true"与在JPA映射中使用mappingBy ="other"相同,都将这一侧标记为在确定对关联的更新时将被忽略的相反侧.

UPDATE: I don't know exactly what Hibernate does when you leave off the mappedBy from either side but I think it may result in less optimal SQL. See also: http://simoes.org/docs/hibernate-2.1/155.html , particularly the section about "inverse="false"". "inverse" is the native Hibernate term for JPA "mappedBy". That is, inverse="true" in a Hibernate mapping is the same as using mappedBy="other" in a JPA mapping, both mark this side as the inverse side that is ignored when determining updates to the association.

这篇关于尝试设置“多"链接时,奇怪的JPA一对多行为.在“一个"上实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆