简体   繁体   English

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

[英]Collecting all child entities from multiple different entities

I have 3 entities A, B and C.我有 3 个实体 A、B 和 C。

  • A contains a one-to-one linked B entity A 包含一对一链接的 B 实体
  • A contains a one-to-many linked List of C entities A 包含 C 实体的一对多链表
  • B contains a one-to-many linked List of C entities B 包含 C 实体的一对多链表

Database-wise there are 5 tables.数据库方面有 5 个表。 The 3 tables for the respective entities and 2 separate linking tables, one containing the links between A and C (A_to_C), and another one containing the links between B and C (B_to_C).各个实体的 3 个表和 2 个单独的链接表,一个包含 A 和 C 之间的链接(A_to_C),另一个包含 B 和 C 之间的链接(B_to_C)。 In my repository I'm trying to retrieve all C entities from a specific A record, meaning the C entities from A itself and the C entities which are linked through B.在我的存储库中,我试图从特定的 A 记录中检索所有 C 实体,这意味着来自 A 本身的 C 实体和通过 B 链接的 C 实体。

In traditional SQL this could be done using something like:在传统的 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';

or (starting from C)或(从 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';

There's no link to the table for B in these SQL examples because A contains the ID for B and it's also the one used in B_to_C so I don't really need it.在这些 SQL 示例中没有指向 B 的表的链接,因为 A 包含 B 的 ID,它也是 B_to_C 中使用的 ID,所以我真的不需要它。 I also know these aren't strictly the same but they produce the same result when I'm only interested in C.我也知道这些并不完全相同,但是当我只对 C 感兴趣时它们会产生相同的结果。

I'm really struggling with how to do this in either CriteriaBuilder (preferably) or JPQL though.不过,我真的很想知道如何在 CriteriaBuilder(最好)或 JPQL 中执行此操作。 I'm still relatively new to jpa so I'm hoping someone here could help me with this.我对 jpa 还是比较陌生,所以我希望这里有人可以帮助我。

I believe that, to even have a chance of succeeding with vanilla JPQL , you would need to convert the association to a bidirectional one (or a unidirectional many-to-one) by adding the @ManyToOne side.我相信,即使有机会在vanilla JPQL上取得成功,您也需要通过添加@ManyToOne方将关联转换为双向关联(或单向多对一)。 You could then start the query from C .然后您可以从C开始查询。 The @OneToMany side, should you want to retain it, becomes the inverse side of the association in such a scenario, though: @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;
}

Once you do that, the JPQL query becomes sth like:一旦你这样做了,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

If you're not OK with making the 'one' side of the association the inverse side, then you're out of luck.如果您不同意将关联的“一侧”设为反面,那么您就不走运了。 The easiest solution is to use a native query.最简单的解决方案是使用本机查询。

Eclipselink JPQL Extensions include an ON clause, so perhaps you could combine ON with MEMBER OF : Eclipselink JPQL 扩展包含一个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

I highly doubt it will work, though, and even if it does, I'd be wary of the generated SQL as it might be suboptimal.不过,我非常怀疑它会起作用,即使它起作用,我也会警惕生成的 SQL,因为它可能不是最理想的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM