我正在尝试设计一个类似的查询:
SELECT *
FROM TableA
WHERE (a AND b AND C) NOT IN
(SELECT *
FROM TableB
WHERE TableB.id != 1234)
我真正想做的是当a,b和c的列值全部在TableB中且ID恰好是1234时,从TableA EXCEPT获取所有记录。
捕获(或者我认为)是我需要以某种方式构造此查询,以便基于上面的查询进行过滤,但是它还需要匹配其他谓词的列表,以使它看起来像这样:
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[]{}));
以上是我的方法之一,但没有任何结果得到正确的结果。
答案 0 :(得分:0)
要解决您的问题,您可以使用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)
in
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)));