保存双向ManyToMany
我有两个以下列方式注释的实体类
@Entity class A { @ManyToMany(mappedBy="A", cascade=CascadeType.ALL) private List b; .. } @Entity class B { @ManyToMany(cascade=CascadeType.ALL) private List a; .. }
如果我存储类’B’的实例,则关系存储在数据库中,类’A’中的getter将返回B的正确子集。 但是,如果我更改“A”中的B列表,更改不会存储在数据库中?
我的问题是,我怎样才能使这两个类中的变化“级联”到另一个类?
编辑:我尝试了删除mappedBy参数和定义JoinTable(和列)的不同变体,但我一直无法找到正确的组合。
最短的答案似乎是你不能,这是有道理的。 在双向多对多关联中,一方必须是主方并且用于持久更改底层连接表。 由于JPA不会维护关联的两端,因此最终可能会出现一旦存储在数据库中就无法重新加载的内存情况。 例:
A a1 = new A(); A a2 = new A(); B b = new B(); a1.getB().add(b); b.getA().add(a2);
如果可以保持此状态,则最终会在连接表中显示以下条目:
a1_id, b_id a2_id, b_id
但在加载时,JPA如何知道你打算只让b知道a2而不是a1? 那个不应该知道b的a2怎么样?
这就是为什么你必须自己维护双向关联(并使上面的例子无法达到,即使在内存中),JPA只会根据它的一面的状态而持久化。
您是否指定了反向连接列?
@Entity class A { @ManyToMany(mappedBy="A", cascade=CascadeType.ALL) private List b; .. } @Entity class B { @ManyToMany @JoinTable ( name="A_B", joinColumns = {@JoinColumn(name="A_ID")}, inverseJoinColumns = {@JoinColumn(name="B_ID")} ) private List a; .. }
这假设一个名为A_B的连接表,其中包含A_ID和B_ID列。
由于关系是双向的,因此应用程序更新关系的一方,另一方也应该更新,并保持同步。 在JPA中,与Java一样, 应用程序或对象模型负责维护关系。 如果您的应用程序添加到关系的一侧,那么它必须添加到另一侧。
这可以通过对象模型中用于处理关系两侧的add或set方法来解决,因此应用程序代码无需担心它。 有两种方法可以解决这个问题,您可以只将关系维护代码添加到关系的一侧,并且只从一侧使用setter(例如使另一方受到保护),或者将其添加到两侧并且确保避免无限循环。
来源: OneToMany #Getters_and_Setters
您是否尝试将mappedBy参数添加到B类的A字段中,如此
@Entity class B { @ManyToMany(cascade=CascadeType.ALL, mappedBy = "b") private List a; .. }
也许在A_M的答案中有一个小错误。 在我看来应该是:
@实体 B级{ @ManyToMany @JoinTable( NAME = “A_B” joinColumns = {@JoinColumn(name =“B_ID”)}, inverseJoinColumns = {@JoinColumn(name =“A_ID”)} ) 私人名单a; .. }