问题描述
我有3个实体A,B和C。
从数据库角度来看,有5个表。各个实体的3个表和2个单独的链接表,一个包含A和C之间的链接(A_to_C),另一个包含B和C之间的链接(B_to_C)。 在我的存储库中,我尝试从特定的A记录中检索所有C实体,这意味着A本身的C实体以及通过B链接的C实体。
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的表的链接,因为A包含B的ID,并且它也是B_to_C中使用的ID,所以我真的不需要它。我也知道这些并不完全相同,但是当我只对C感兴趣时,它们会产生相同的结果。
尽管我在CriteriaBuilder(最好)或JPQL中如何做到这一点确实很挣扎。 我对jpa还是比较陌生,所以希望这里有人可以帮助我。
解决方法
我相信,要想成功使用香草JPQL ,您还需要通过添加{将关联转换为双向关联(或单向多对一) {1}}一侧。然后,您可以从@ManyToOne
开始查询。在这种情况下,C
端(如果要保留它)将成为关联的相反端,
@OneToMany
执行完此操作后,JPQL查询将变为:
@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;
}
如果您不赞成将关联的“一”面设为反面,那么您就不走运了。最简单的解决方案是使用本机查询。
Eclipselink 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
子句,因此也许可以将ON
与ON
组合在一起:
MEMBER OF
我非常怀疑它是否会工作,即使可以,我也会对生成的SQL保持警惕,因为它可能不是最佳选择。