保存双向ManyToMany

时间:2009-05-05 12:14:36

标签: java jpa

我有两个以下列方式注释的实体类

@Entity
class A {
   @ManyToMany(mappedBy="A", cascade=CascadeType.ALL)
   private List<B> b;
 ..
}

@Entity
class B {
   @ManyToMany(cascade=CascadeType.ALL)
   private List<A> a;
 ..
}

如果我存储类'B'的实例,则关系存储在数据库中,类'A'中的getter将返回B的正确子集。但是,如果我更改“A”中的B列表,更改不会存储在数据库中?

我的问题是,我怎样才能使这两个类中的变化“级联”到另一个类?

编辑:我尝试过删除mappedBy参数和定义JoinTable(和列)的不同变体,但我一直无法找到正确的组合。

5 个答案:

答案 0 :(得分:16)

最短的答案似乎是你做不到而且这是有道理的。在双向多对多关联中,一方必须是主方,并且用于持久更改底层连接表。由于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只会根据它的一面的状态而持续存在。

答案 1 :(得分:3)

您是否指定了反向连接列?

@Entity
class A {
   @ManyToMany(mappedBy="A", cascade=CascadeType.ALL)
   private List <B> b;
   ..
}

@Entity 
class B { 
   @ManyToMany 
   @JoinTable (
       name="A_B",
       joinColumns = {@JoinColumn(name="A_ID")},
       inverseJoinColumns = {@JoinColumn(name="B_ID")}
   )
   private List<A> a; 
   .. 
} 

假设一个名为A_B的连接表,其中包含A_ID和B_ID列。

答案 2 :(得分:1)

  

由于关系是双向的,因此应用程序更新   关系的一方,另一方也应该更新,   并保持同步。在JPA中,就像在Java中一般一样   应用程序的责任,或维护的对象模型   关系。如果你的应用程序添加到一个   关系,然后它必须添加到另一方。

     

这可以通过对象模型中的add或set方法来解决   处理关系的两面,所以应用程序代码   不需要担心它。有两种方法可以解决这个问题,   您只能将关系维护代码添加到一侧   关系,只从一侧使用setter(如   使另一方受到保护),或将其添加到双方并确保   你避免无限循环。

来源:OneToMany#Getters_and_Setters

答案 3 :(得分:0)

您是否尝试将mappedBy参数添加到B类的A字段中,如此

@Entity
class B {
   @ManyToMany(cascade=CascadeType.ALL, mappedBy = "b")
   private List<A> a;
 ..
}

答案 4 :(得分:0)

也许A_M的回答中有一个小错误。 在我看来应该是:

   @Entity
   class B { 
   @ManyToMany 
   @JoinTable (
       name="A_B",
       joinColumns = {@JoinColumn(name="B_ID")},
       inverseJoinColumns = {@JoinColumn(name="A_ID")}
   )
   private List a; 
   .. 
}