【问题标题】:JPA Criteria Query with multiple columns in subqueryJPA Criteria Query 在子查询中有多个列
【发布时间】:2018-01-23 19:03:29
【问题描述】:

我正在尝试设计这样的查询:

SELECT *
FROM TableA
WHERE (a AND b AND C) NOT IN
    (SELECT *
     FROM TableB
     WHERE TableB.id != 1234)

我真正想做的是从 TableA 中获取所有记录,除非 a、b 和 c 的列值都在 TableB 中并且 ID 恰好是 1234。

问题(或者我认为)是我需要以某种方式构造这个查询,以便我根据上面的查询进行过滤,但它还需要匹配其他谓词列表,使其看起来像这个:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<TableA> q = cb.createQuery(TableA.class);
Root<TableA> c = q.from(TableA.class);


Subquery<TableB> sq = q.subquery(TableB.class);
Root<TableB> ac = sq.from(TableB.class);

List<Predicate> predicates = new ArrayList<Predicate>();

sq.select(ac);
sq.where(cb.equal(ac.get("id"), 1234));

predicates.add(cb.not(cb.in(c.get("a")).value(sq)));
predicates.add(cb.not(cb.in(c.get("b")).value(sq)));
predicates.add(cb.not(cb.in(c.get("c")).value(sq)));


.... 
more predicates added
....

q.where(predicates.toArray(new Predicate[]{}));

以上是我的一种方法,但没有得到正确的结果。

【问题讨论】:

    标签: mysql hibernate jpa hibernate-criteria


    【解决方案1】:

    要解决您的问题,您可以将带有 IN 子句的查询转换为带有 EXISTS 子句的查询。 示例:

    SELECT *
       FROM TableA ta
    WHERE (ta.a, ta.b) NOT IN
     (SELECT tb.a, tb.c
        FROM TableB tb
        WHERE tb.id != 1234)
    

    SELECT *
      FROM TableA ta
     WHERE NOT EXISTS
         (SELECT 1
           FROM TableB tb
            WHERE ta.a = tb.a AND ta.b = tb.b 
          AND TableB.id != 1234)
    

    您使用 JPA CriteriaBuilder 的代码将被修改为:

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<TableA> criteria = cb.createQuery(TableA.class);
    Root<TableA> rootTableA = criteria.from(TableA.class);
    
    Subquery<TableB> sq = criteria.subquery(TableB.class);
    Root<TableB> rootTableB = sq.from(TableB.class);
    sq.select(rootTableB);
    
    List<Predicate> subQueryPredicates = new ArrayList<Predicate>();
    subQueryPredicates.add(cb.equal(rootTableA.get("a"), rootTableB.get("a")));
    subQueryPredicates.add(cb.equal(rootTableA.get("b"), rootTableB.get("b")));
    subQueryPredicates.add(cb.equal(rootTableB.get("id"), 1234));
    sq.where(subQueryPredicates.toArray(new Predicate[]{}));
    
    criteria.where(cb.not(cb.exists(sq)));
    

    【讨论】:

      猜你喜欢
      • 2021-08-30
      • 1970-01-01
      • 1970-01-01
      • 2012-09-07
      • 2011-08-01
      • 2017-07-20
      • 2012-07-19
      • 1970-01-01
      相关资源
      最近更新 更多