从多个不同实体收集所有子实体
Collecting all child entities from multiple different entities
我有 3 个实体 A、B 和 C。
- A 包含一对一 linked B 实体
- A 包含一对多 linked 列表 C 实体
- B 包含一对多 linked 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
子句,因此也许您可以将 ON
与 MEMBER 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 保持警惕,因为它可能不是最理想的。
我有 3 个实体 A、B 和 C。
- A 包含一对一 linked B 实体
- A 包含一对多 linked 列表 C 实体
- B 包含一对多 linked 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
子句,因此也许您可以将 ON
与 MEMBER 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 保持警惕,因为它可能不是最理想的。