当前位置: 代码迷 >> java >> @ManyToMany JPA关系,在联接表和英国中使用2度关系
  详细解决方案

@ManyToMany JPA关系,在联接表和英国中使用2度关系

热度:71   发布时间:2023-08-04 09:31:22.0

我有这个实体模型(简化):

@Entity
class A {
  @Id
  String id;

  Collection<B> bs;
}

@Entity
class B {
  @Id
  String id;

  @ManyToOne
  @JoinColumn(name = "c_id", nullable = false)
  C c;
}

@Entity
class C {
  @Id
  String id;
}

在A和B之间添加联接表(多对多关系)并使用A.id和Bcid强制执行复合UK的最佳方法是什么?

我尝试过这样的事情:

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable
        (name = "a_b",
                joinColumns = @JoinColumn(name = "a_id"),
                inverseJoinColumns = {
                        @JoinColumn(name = "b_id", referencedColumnName = "id"),
                        @JoinColumn(name = "c_id", referencedColumnName = "c_id")},
                uniqueConstraints = @UniqueConstraint(name = "uk_a_c", columnNames = {"a_id", "c_id"}))

但是我得到了MultipleBagFetchException ,这很奇怪。 它必须与c_id不是主键的一部分有关。 如果我从inverseJoinColumns删除c_id ,它会按预期工作,但这不是我所需要的。

如果在B和C之间是一对一的关联,则可以在这两个之间共享主键,这样

B.id = C.id = B.c.id

然后,联接表唯一键可以在A.id和B.id之间。

我的最终映射如下所示:

@Entity
@EntityListeners(ABListener.class)
@Table(name = "a_b", uniqueConstraints =
@UniqueConstraint(name = "uk_rel_a_b", columnNames = {"a_id", "c_id"}))
public class AB extends BaseEntity<Long> {

    private Long id;

    @ManyToOne(optional = false)
    @JoinColumn(name = "a_id")
    private A a;

    @ManyToOne(optional = false)
    @JoinColumn(name = "b_id")
    private B b;

    @ManyToOne(optional = false)
    @JoinColumn(name = "c_id")
    private C c;

    public AB(A a, B b) {
        this.a = a;
        this.b = b;
    }
    /* rest of the class */
}

和一个监听器来处理C设置:

public class ABListener {

    @PrePersist
    @PreUpdate
    void handleCUpdate(AB ab) {
        if (ab.getB() != null) {
            ab.setC(ab.getB().getC());
        }
    }

}