我想使用Criteria API使用2个WHERE条件创建查询。我有一个具有嵌套字段(@OneToMany等)的实体A。我想创建具有以下条件的select:
entity A.fieldB.fieldC.id = X and A.fieldB.fieldD.id = Y
public <T> List<T> getEntityWithParams(Map<Field, Object> params, Reportable<T> reportable) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<T> query = builder.createQuery(reportable.getReportEntityClass());
Root<T> from = query.from(reportable.getReportEntityClass());
Predicate conditions = builder.conjunction();
Path<Object> path = from.join("activityCategories")
.get("processActivity")
.get("personalData")
.get("company")
.get("id");
Path<Object> path2 = from.join("activityCategories")
.get("processActivity")
.get("personalData")
.get("administrator")
.get("id");
// builder.and(conjunction, builder.equal(path, value), builder.equal(path2, 4)))
conditions = builder.and(builder.equal(path, 1), builder.equal(path2, 4));
List<T> typedQuery = em.createQuery(query
.select(from)
.where(conditions)
.distinct(true)).getResultList();
当我使用2条路径时,Hibernate会创建JOIN两次:
select
distinct processing0_.id as id1_51_,
processing0_.data_wpr as data_wpr2_51_,
processing0_.opr as opr3_51_,
processing0_.aktywna as aktywna4_51_,
processing0_.id_spolka as id_spolk7_51_,
processing0_.nazwa as nazwa5_51_,
processing0_.nazwa_kategorii_podpowierzenia_przetwarzania as nazwa_ka6_51_
from
odo.odo_kategoria_czynnosci_przetwarzania processing0_
inner join
odo.odo_czynnosc_kategoria activityca1_
on processing0_.id=activityca1_.id_kategoria_czynnosci
inner join
odo.odo_czynnosc_kategoria activityca2_
on processing0_.id=activityca2_.id_kategoria_czynnosci cross
join
odo.odo_czynnosc_przetwarzania processing3_ cross
join
odo.odo_zbior personalda4_ cross
join
odo.odo_czynnosc_przetwarzania processing5_ cross
join
odo.odo_zbior personalda6_
where
activityca1_.id_czynnosc=processing3_.id
and processing3_.id_zbior=personalda4_.id
and activityca2_.id_czynnosc=processing5_.id
and processing5_.id_zbior=personalda6_.id
and personalda4_.id_zbior_spolka=1
and personalda6_.id_zbior_administrator=4
因此结果不正确。此外,还有使用的CROSS JOIN。您是否知道如何准备这样的查询:
select
distinct processing0_.id as id1_51_,
processing0_.data_wpr as data_wpr2_51_,
processing0_.opr as opr3_51_,
processing0_.aktywna as aktywna4_51_,
processing0_.id_spolka as id_spolk7_51_,
processing0_.nazwa as nazwa5_51_,
processing0_.nazwa_kategorii_podpowierzenia_przetwarzania as nazwa_ka6_51_
from
odo.odo_kategoria_czynnosci_przetwarzania processing0_
inner join
odo.odo_czynnosc_kategoria activityca1_
on processing0_.id=activityca1_.id_kategoria_czynnosci
inner join
join
odo.odo_zbior personalda4_ on personalda4_ = processing0_.id_zbior
where
personalda4_.id_zbior_spolka=1
and personalda4_.id_zbior_administrator=4
答案 0 :(得分:0)
您应该将gets替换为连接。
Root<T> from = query.from(reportable.getReportEntityClass());
Join<Type1, Type2> personalData = from.join("activityCategories")
.join("processActivity")
.join("personalData")
Path<Long> path = personalData.get("company").get("id");
Path<Long> path2 = personalData.get("administrator").get("id");
在上面的代码中,我假设在您的数据库中,您已经将company.id
和administrator.id
作为FK
存储在personalData
表中。这是(我认为)仅在值得用get替换join的情况下使用(因此,您有一个join-更好的性能)