JPA:抓住一对多关系与多个连接表之间

JPA: Grab One-to-Many relationship with multiple join tables inbetween

我有 4 个表:表 1、表 2、表 3、表 4。

我的意图是 Table1 将有一个多对多成员到 Table4。即Table1会有Table4的List成员

public class Table1 implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(updatable = false, nullable = false)
    @JsonView(View.class)
    private UUID id;

   List<Table4> list; //This is the member of the question

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "table_2_id")
    @JsonView(View.class)
    private Table2 table2;

   
    ....
}

public class Table2 implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(updatable = false, nullable = false)
    @JsonView(View.class)
    private UUID id;
   
    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "table_3_id")
    @JsonView(View.class)
    private Table3 table3;
}

public class Table3 implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(updatable = false, nullable = false)
    @JsonView(View.class)
    private UUID id;
   
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "table_4_id")
    @JsonView(View.class)
    private Table4 table4;
}

public class Table4 implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(updatable = false, nullable = false)
    @JsonView(View.class)
    private UUID id;
   
    ....
}

我尝试使用类似

的东西
@JoinTable(
        name = "Table3", 
        joinColumns = @JoinColumn(name = "table_2_id"), 
        inverseJoinColumns = @JoinColumn(name = "table_4_id")
    )

...试图映射多对多实体,但这种方法似乎行不通,因为我有两个中间 tables.

我如何从 table 中获取一个多对多关系的 table 列表?

为什么不直接使用 getter 方法 returns 您的 Table4 列表,如下所示?您已经准备好所有映射。

public class Table1 implements Serializable {
...
  public List<Table4> getTable4List(){
     //navigate to the list of table4 through the other tables
     //return null (or empty list) if table2, table3 are null or empty
  }

您可以将 getter 放在实体中以遵循域驱动设计,但您也可以将其放在服务事务方法中...

如果您只需要读取值,您可以尝试使用“特殊”table名称:

@JoinTable(
    name = "(select * from Table2 t2 join Table3 t3 on ...)", 
    joinColumns = @JoinColumn(name = "table_2_id"), 
    inverseJoinColumns = @JoinColumn(name = "table_4_id")
)

但这就是问题所在,您不能写入它,因为这不再是双向映射。你想在这里做的事情通常是通过遍历 Java 代码中的图形,或者使用 DTO 来完成,我认为 Blaze-Persistence Entity Views 是完美的匹配。

我创建了库以允许在 JPA 模型和自定义接口或抽象 class 定义的模型之间轻松映射,类似于 Spring 类固醇数据投影。这个想法是您按照自己喜欢的方式定义目标结构(领域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

您的用例的 DTO 模型与 Blaze-Persistence 实体视图类似:

@EntityView(Table1.class)
public interface Table1Dto {
    @IdMapping
    UUID getId();
    String getName();
    @Mapping("table2.table3.table4")
    Set<Table4Dto> getTable4();

    @EntityView(Table4.class)
    interface Table4Dto {
        @IdMapping
        UUID getId();
        String getName();
    }
}

查询就是将实体视图应用于查询,最简单的就是通过 id 进行查询。

Table1Dto a = entityViewManager.find(entityManager, Table1Dto.class, id);

Spring 数据集成让您几乎可以像 Spring 数据投影一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<Table1Dto> findAll(Pageable pageable);

最棒的是,它只会获取实际需要的状态!