如何在 jpa 标准中进行 JOIN FETCH
how to do a JOIN FETCH in jpa criteria
我正在尝试将下面的查询转换为条件 api。
SELECT er from ereturn er JOIN FETCH product_item pi ON pi.ereturn_id = er.id WHERE pi.status = "RECEIVED"
像这样:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Ereturn> criteria = builder.createQuery( Ereturn.class );
Root<Ereturn> er = criteria.from(Ereturn.class);
Join<Ereturn, ProductItem> productItemJoin = er.join("productItems", JoinType.LEFT);
Fetch<Ereturn, ProductItem> productItemFetch = er.fetch("productItems", JoinType.LEFT);
List<Predicate> predicates = new ArrayList<>();
predicates.add(builder.equal( productItemJoin.get( "status" ), "RECEIVED"));
criteria.where(
builder.and(predicates.toArray(new Predicate[predicates.size()]))
);
List<Ereturn> ers = em.createQuery( criteria )
.getResultList();
问题是休眠生成了这个查询:
select
ereturn0_.id as ...
...
productite6_.id as ...
...
from
ereturn ereturn0_
join
product_item productite1_
on ereturn0_.id = productite1_.ereturn
join
product_item productite6_
on ereturn0_.id = productite6_.ereturn
where
productite1_.status='RECEIVED';
问题:在从两个表(ereturn 和 productItem)获取字段时,我如何告诉 hibernate 仅使用 1 个连接生成此查询?
显然转换是可行的方法,但是我们需要考虑到 .fetch()/.join() 是通用方法,因此转换有点不同
选项 1
Fetch<Ereturn, ProductItem> productItemFetch = er.fetch("productItems", JoinType.LEFT);
Join<Ereturn, ProductItem> productItemJoin = (Join<Ereturn, ProductItem>) productItemFetch;
选项 2
Join<Ereturn, ProductItem> productItemJoin = (Join<Ereturn, ProductItem>) er.<Ereturn, ProductItem>fetch("productItems", JoinType.LEFT)
现在查询与我要查找的内容是正确的:
select
...
from
ereturn ereturn0_
left outer join
product_item productite5_
on ereturn0_.id=productite5_.ereturn
where
and productite5_.status=?
这的确是个问题,但您的答案显示了另外两个表格,这不是正确答案。试试这个:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Ereturn> q = cb.createQuery(Ereturn.class);
Root<Ereturn> r = q.from(Ereturn.class);
r.fetch("productItem", JoinType.LEFT);
// here join with the root instead of the fetch
// casting the fetch to the join could cause portability problems
// plus, not nice
q.where(cb.equal(r.get("productItem").get("status"), "received"));
Ereturn ereturn= em.createQuery(q).getSingleResult();
这给出了
select ereturn0_.id as id1_0_0_, productite1_.id as id1_1_1_, ereturn0_.parentEreturn_id as parentCo2_0_0_, ereturn0_.productItem_id as productI3_0_0_, productite1_.status as status2_1_1_
from Ereturn ereturn0_
left outer join ProductItem productite1_ on ereturn0_.productItem_id=productite1_.id
where productite1_.status=?
请参阅 JPA 2 Criteria Fetch Path Navigation 更下方的答案。
我正在尝试将下面的查询转换为条件 api。
SELECT er from ereturn er JOIN FETCH product_item pi ON pi.ereturn_id = er.id WHERE pi.status = "RECEIVED"
像这样:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Ereturn> criteria = builder.createQuery( Ereturn.class );
Root<Ereturn> er = criteria.from(Ereturn.class);
Join<Ereturn, ProductItem> productItemJoin = er.join("productItems", JoinType.LEFT);
Fetch<Ereturn, ProductItem> productItemFetch = er.fetch("productItems", JoinType.LEFT);
List<Predicate> predicates = new ArrayList<>();
predicates.add(builder.equal( productItemJoin.get( "status" ), "RECEIVED"));
criteria.where(
builder.and(predicates.toArray(new Predicate[predicates.size()]))
);
List<Ereturn> ers = em.createQuery( criteria )
.getResultList();
问题是休眠生成了这个查询:
select
ereturn0_.id as ...
...
productite6_.id as ...
...
from
ereturn ereturn0_
join
product_item productite1_
on ereturn0_.id = productite1_.ereturn
join
product_item productite6_
on ereturn0_.id = productite6_.ereturn
where
productite1_.status='RECEIVED';
问题:在从两个表(ereturn 和 productItem)获取字段时,我如何告诉 hibernate 仅使用 1 个连接生成此查询?
显然转换是可行的方法,但是我们需要考虑到 .fetch()/.join() 是通用方法,因此转换有点不同
选项 1
Fetch<Ereturn, ProductItem> productItemFetch = er.fetch("productItems", JoinType.LEFT);
Join<Ereturn, ProductItem> productItemJoin = (Join<Ereturn, ProductItem>) productItemFetch;
选项 2
Join<Ereturn, ProductItem> productItemJoin = (Join<Ereturn, ProductItem>) er.<Ereturn, ProductItem>fetch("productItems", JoinType.LEFT)
现在查询与我要查找的内容是正确的:
select
...
from
ereturn ereturn0_
left outer join
product_item productite5_
on ereturn0_.id=productite5_.ereturn
where
and productite5_.status=?
这的确是个问题,但您的答案显示了另外两个表格,这不是正确答案。试试这个:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Ereturn> q = cb.createQuery(Ereturn.class);
Root<Ereturn> r = q.from(Ereturn.class);
r.fetch("productItem", JoinType.LEFT);
// here join with the root instead of the fetch
// casting the fetch to the join could cause portability problems
// plus, not nice
q.where(cb.equal(r.get("productItem").get("status"), "received"));
Ereturn ereturn= em.createQuery(q).getSingleResult();
这给出了
select ereturn0_.id as id1_0_0_, productite1_.id as id1_1_1_, ereturn0_.parentEreturn_id as parentCo2_0_0_, ereturn0_.productItem_id as productI3_0_0_, productite1_.status as status2_1_1_
from Ereturn ereturn0_
left outer join ProductItem productite1_ on ereturn0_.productItem_id=productite1_.id
where productite1_.status=?
请参阅 JPA 2 Criteria Fetch Path Navigation 更下方的答案。