Eclipselink 2.5.1-RC1 JPA 3-Way ManyToMany:结点 table 记录的自动 addition/removal

Eclipselink 2.5.1-RC1 JPA 3-Way ManyToMany: Automatic addition/removal of junction table records

我有 3 个实体:X、Y、Z。X 由 Y 的集合组成,Y 将每个 Y 与 Z 相关联。(Y-Z) -> X 关联在 junction/link [=43 中维护=] 使用三个引用作为复合主键调用 YZ_2_X_Map:YId、ZId、XId。

以下是 X 实体的代码:

@Entity
public class X implements Serializable {

  // Properties

  //bi-directional many-to-one association to YZ_2_X_Map 
  @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="x")
  @JoinTable(name="YZ_2_X_Map",
    joinColumns=
      @JoinColumn(name="XId")
  )
  private List<YZ_2_X_Map> yZList;

  public void setYZList(List<YZ_2_X_Map> yZList) {
    this.yZList = yZList;
  }
}

以下是 YZ_2_X_Map 实体的代码:

public class YZ_2_X_Map implements Serializable {
  private static final long serialVersionUID = 1L;

  @EmbeddedId
  private YZ_2_X_MapPK id;

  //bi-directional many-to-one association to Y
  @ManyToOne
  @JoinColumn(name="YId")
  private Y y;

  //bi-directional many-to-one association to Z
  @ManyToOne
  @JoinColumn(name="ZId")
  private Z z;

  //bi-directional many-to-one association to X
  @ManyToOne
  @JoinColumn(name="XId")
  private X x;

  // Methods
}

我的期望是,每当我坚持 X 时,根据 yZList 中的条目,YZ_2_X_Map 连接点 table 中的记录应该是 inserted/deleted。

使用上面的代码,向 yzList 添加新条目会按照我的预期在 YZ_2_X_Map table 中添加新记录。

但是,从 yzList 中删除条目不会从 YZ_2_X_Map table 中删除相应的记录。

我还尝试从 class X 中的 @OneToMany 注释中删除 mappedBy,并从 class YZ_2_X_Map 中删除 x 属性。在这种情况下,虽然从 yzList 中删除条目会删除相应的记录,但将新条目添加到 yzList 并持久化 X 会生成 INSERT into YZ_2_X_Map 但会抛出重复条目异常。

请告诉我如何根据 yZList 中的条目在 YZ_2_X_Map table 中实现自动 addition/removal 记录的期望。

您为 YZ_2_X_Map table 创建了一个实体,但随后创建了一个 1:m 映射到使用 YZ_2_X_Map 连接 table - 实际上是一个连接 table 到一个连接 table。 mappedBy="x" 告诉映射要使用的外键包含在 YZ_2_X_Map.x 映射中。 Join table 或 join 列仅在这是关系的拥有方或单向时才需要。

只需要:

  public class X implements Serializable {
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="x")
    private List<YZ_2_X_Map> yZList;
    ...

如果您希望 JPA 运行以便从 yZList 中删除一个实体会导致 YZ_2_X_Map 实体和行被删除,那么您需要将关系标记为私有(特定于 EclipseLink)或者如果使用 JPA 2.0,则 orphanRemoval=true。这将强制 JPA 在实体从映射中取消引用时也将其删除。

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, orphanRemoval=true, mappedBy="x")

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="x")
@PrivateOwned
private List<YZ_2_X_Map> yZList;