从多个不同实体收集所有子实体

Collecting all child entities from multiple different entities

我有 3 个实体 A、B 和 C。

数据库方面有 5 个 table。各自实体的 3 个 table 和 2 个单独的 linking table,其中一个包含 A 和 C 之间的 link(A_to_C),以及另一个包含 B 和 C 之间的 link (B_to_C)。 在我的存储库中,我试图从特定的 A 记录中检索所有 C 实体,这意味着来自 A 本身的 C 实体和 link 通过 B.

编辑的 C 实体

在传统的 SQL 中,这可以使用类似的东西来完成:

select C.*
from A
left join A_to_C on A_to_C.A_ID = A.ID
left join B_to_C on B_to_C.B_ID = A.B_ID
inner join C on C.ID = A_to_C.C_ID OR C.ID = B_to_C.C_ID
where A.ID = '1';

或(从C开始)

select C.*
from C
left join A_to_C on A_to_C.C_ID = C.ID
left join B_to_C on B_to_C.C_ID = C.ID
inner join A on A.B_ID = B_to_C.B_ID OR
                A.ID = A_to_C.A_ID
where A.ID = '1';

在这些 SQL 示例中,B 的 table 没有 link,因为 A 包含 B 的 ID,它也是 B_to_C 中使用的 ID,所以我真的不需要它。我也知道它们并不完全相同,但是当我只对 C 感兴趣时它们会产生相同的结果。

不过,我真的很困惑如何在 CriteriaBuilder(最好)或 JPQL 中执行此操作。 我对 jpa 还是比较陌生,所以我希望这里有人可以帮助我。

我相信,即使有机会使用 vanilla JPQL 取得成功,您也需要将关联转换为双向关联(或单向关联 many-to-one ) 通过添加 @ManyToOne 边。然后您可以从 C 开始查询。 @OneToMany 面,如果您想保留它,在这种情况下会变成关联的反面,但是:

@Entity
public class C {

    @ManyToOne
    @JoinTable
    private B b;

    @ManyToOne
    @JoinTable
    private A a;
}

@Entity
public class B {

    @ManyToOne
    @JoinTable
    private A a;

    @OneToMany(mappedBy = "b")
    private List<C> cs;
}

@Entity
public class A {

    @OneToMany(mappedBy = "a")
    private List<B> bs;


    @OneToMany(mappedBy = "a")
    private List<C> cs;
}

一旦你这样做了,JPQL 查询就会变成这样:

SELECT c FROM C c
LEFT JOIN c.a a
LEFT JOIN c.b b
LEFT JOIN b.a a2
WHERE a.id = :id OR a2.id = :id

如果您不同意将关联的 'one' 侧设为相反侧,那么您就不走运了。最简单的解决方案是使用本机查询。

Eclipselink JPQL Extensions 包含一个 ON 子句,因此也许您可以将 ONMEMBER OF 结合使用:

SELECT c FROM C c
LEFT JOIN A a ON c MEMBER OF a.cs
LEFT JOIN B b ON c MEMBER OF b.cs
LEFT JOIN A a2 ON b MEMBER OF a2.cs
WHERE a.id = :id OR a2.id = :id

不过,我非常怀疑它是否会起作用,即使它起作用,我也会对生成的 SQL 保持警惕,因为它可能不是最理想的。