JPA条件查询:带条件谓词“ in”的where子句中的子查询

时间:2019-09-02 15:14:55

标签: java oracle jpa eclipselink criteria

我具有以下设计(伪代码):

table A (id int, cond int)
table B (id int, a_id int)

也就是说,B.a_idA.id的外键。并非B引用了A中的所有条目。B包含的条目比A还要多。

A和B之间的关系仅用B表示,而不用A表示:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "a_id")
private A a;

我想为此SQL建立JPA标准查询(查询1)

select A.* from A where A.id in (select distinct B.a_id from B) or A.cond = 1

此刻我找到了解决方案:

EntityManager em = ...
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<A> qa = cb.createQuery(A.class);
Root<A> ra = qa.from(A.class);

Subquery<B> sqb = qa.subquery(B.class);
Root<B> srb = sqb.from(B.class);

qa = qa.select(ra).distinct(true).where(cb.or
    ( 
      cb.equal(ra, srb.get(B_.a))
    , cb.equal(ra.get(A_.cond), 1)
    ));

em.createQuery(qa).getResultStream().forEach(System.out::println);

EclipseLink将其转换为AB之间的联接以及最终的distinct选择(查询2)

SELECT DISTINCT t0.ID, t0.COND FROM A t0, B t1 WHERE ((A.ID = B.A_ID) OR (A.COND = ?))
  bind => [1]

但是,由于B的条目太多,所以我想知道第一个select distinct B.a_id from B是否会更好。

在where子句中带有子查询的查询1的相应JPA条件查询表达式是什么?

(我想知道解决方案,尽管该数据库具有查询优化器,并且可以选择估计的最佳执行路径)

编辑

对于我的数据和索引,查询优化器为查询1选择一个执行计划,估计成本为3,而对查询2估计为7。

还有另一种形式(查询3)

select A.* from A where exists (select 1 from B where B.a_id = A.id) or A.cond = 1

查询优化器为其选择与查询1相同的执行计划。

qa = qa.select(ra).distinct(true).where(cb.or
    ( 
      cb.exists(qb.select(rb).where(cb.equal(ra, rb.get(B_.a))))
    , cb.equal(ra.get(A_.cond), 1)
    ));

0 个答案:

没有答案