我有以下SQL查询:
select
A.A_ID,
B.Lib,
A.Lib,
C.Lib,
(SELECT count(*) FROM X WHERE A.A_ID = X.A_ID) AS countX,
(SELECT count(*) FROM Y WHERE A.A_ID = Y.A_ID) AS countY,
(SELECT count(*) FROM Z WHERE A.A_ID = Z.A_ID) AS countZ
from
A
left outer join
C
on A.C_ID=C.C_ID
left outer join
B
on A.B_ID=B.B_ID;
我想使用JPA Criteria API创建此查询,所以我做了如下操作:
final CriteriaBuilder builder = getCriteriaBuilder();
final CriteriaQuery<A_DTO> criteriaQuery = builder.createQuery(A_DTO.class);
final Root<A> aRoot = criteriaQuery.from(A.class);
// LEFT OUTER JOIN B
Join<A, B> bJoin = aRoot.join(A_.bID, JoinType.LEFT);
// LEFT OUTER JOIN C
Join<A, C> cJoin = aRoot.join(A_.cID, JoinType.LEFT);
// (SELECT count(*) FROM X WHERE A.A_ID = X.A_ID) AS countX
final Subquery<X> xSubquery = criteriaQuery.subquery(X.class);
final Root<X> xRoot = xSubquery.from(X.class);
xRoot.alias("countX");
xSubquery.select(xRoot);
xSubquery.where(builder.equal(xRoot.get(X_.a).get(A_.aID), aRoot.get(A_.aID)));
// (SELECT count(*) FROM Y WHERE A.A_ID = Y.A_ID) AS countY
final Subquery<Y> ySubquery = criteriaQuery.subquery(Y.class);
final Root<Y> yRoot = ySubquery.from(Y.class);
yRoot.alias("countY");
ySubquery.select(yRoot);
ySubquery.where(builder.equal(yRoot.get(Y_.a).get(A_.aID), aRoot.get(A_.aID)));
// (SELECT count(*) FROM Z WHERE A.A_ID = Z.A_ID) AS countZ
final Subquery<Z> zSubquery = criteriaQuery.subquery(Z.class);
final Root<Z> zRoot = zSubquery.from(Z.class);
zRoot.alias("countZ");
zSubquery.select(zRoot);
zSubquery.where(builder.equal(zRoot.get(Z_.a).get(A_.aID), aRoot.get(A_.aID)));
// Selection
criteriaQuery.multiselect(aRoot.get(A_.aID),
bJoin.get(B_.lib),
aRoot.get(A_.lib),
cJoin.get(C_.lib),
builder.count(xRoot),
builder.count(yRoot),
builder.count(zRoot));
return getEntityManager().createQuery(criteriaQuery);
但这对我不起作用,而是生成以下SQL查询:
select
a0_.aID as col_0_0_,
b2_.Lib as col_1_0_,
a0_.Lib as col_3_0_,
c1_.Lib as col_4_0_,
count(countX) as col_5_0_,
count(countY) as col_6_0_,
count(countZ) as col_7_0_
from
A a0_
left outer join
C c1_
on a0_.cID=c1_.cID
left outer join
B b2_
on a0_.bID=b2_.bID;
这将引发以下SQL异常:
WARN o.h.e.j.s.SqlExceptionHelper-SQL错误:904,SQLState:42000
错误o.h.e.j.s.SqlExceptionHelper-ORA-00904:“ countZ”:无效 标识符
我该如何解决这个问题?
我已经使用以下代码解决了这个问题:
final CriteriaBuilder builder = getCriteriaBuilder();
final CriteriaQuery<A_DTO> criteriaQuery = builder.createQuery(A_DTO.class);
final Root<A> aRoot = criteriaQuery.from(A.class);
// LEFT OUTER JOIN B
Join<A, B> bJoin = aRoot.join(A_.bID, JoinType.LEFT);
// LEFT OUTER JOIN C
Join<A, C> cJoin = aRoot.join(A_.cID, JoinType.LEFT);
// (SELECT count(*) FROM X WHERE A.A_ID = X.A_ID) AS countX
final Subquery<Long> xSubquery = criteriaQuery.subquery(Long.class);
final Root<X> xRoot = xSubquery.from(X.class);
final Expression<Long> xCount = builder.count(xRoot);
xSubquery.select(xCount);
xSubquery.where(builder.equal(xRoot.get(X_.a).get(A_.aID), aRoot.get(A_.aID)));
// (SELECT count(*) FROM Y WHERE A.A_ID = Y.A_ID) AS countY
final Subquery<Long> ySubquery = criteriaQuery.subquery(Long.class);
final Root<Y> yRoot = ySubquery.from(Y.class);
final Expression<Long> yCount = builder.count(yRoot);
ySubquery.select(yCount);
ySubquery.where(builder.equal(yRoot.get(Y_.a).get(A_.aID), aRoot.get(A_.aID)));
// (SELECT count(*) FROM Z WHERE A.A_ID = Z.A_ID) AS countZ
final Subquery<Long> zSubquery = criteriaQuery.subquery(Long.class);
final Root<Z> zRoot = zSubquery.from(Z.class);
final Expression<Long> zCount = builder.count(zRoot);
zSubquery.select(zCount);
zSubquery.where(builder.equal(zRoot.get(Z_.a).get(A_.aID), aRoot.get(A_.aID)));
// Selection
criteriaQuery.multiselect(aRoot.get(A_.aID),
bJoin.get(B_.lib),
aRoot.get(A_.lib),
cJoin.get(C_.lib),
xSubquery.getSelection(),
ySubquery.getSelection(),
zSubquery.getSelection());
return getEntityManager().createQuery(criteriaQuery);
但是当我想根据计数值选择结果或使用它对结果进行排序时,我必须按以下方式更改查询:
WITH cte AS ( select
A.A_ID,
B.Lib,
A.Lib,
C.Lib,
(SELECT count(*) FROM X WHERE A.A_ID = X.A_ID) AS countX,
(SELECT count(*) FROM Y WHERE A.A_ID = Y.A_ID) AS countY,
(SELECT count(*) FROM Z WHERE A.A_ID = Z.A_ID) AS countZ
from
A
left outer join
C
on A.C_ID=C.C_ID
left outer join
B
on A.B_ID=B.B_ID)
SELECT * FROM cte
WHERE countX > 2
ORDER BY countY, countZ DESC;
现在我不知道如何在JPA Criteria API中创建此通用表表达式。