I'm trying, as in title, to insert a subquery in select clause like in this simple SQL:
SELECT id, name, (select count(*) from item) from item
this is obviously only a mock query just to make my point. (The point would be to get the last invoice for each item returned by the query.)
I've tried this:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> c = cb.createTupleQuery();
Root<Item> item= c.from(Item.class);
Subquery<Long> scount = c.subquery(Long.class);
Root<Item> sarticolo = scount.from(Item.class);
scount.select(cb.count(sitem));
c.multiselect(item.get("id"),item.get("nome"), scount);
Query q = em.createQuery(c);
q.setMaxResults(100);
List<Tuple> result = q.getResultList();
for(Tuple t: result){
System.out.println(t.get(0) + ", " + t.get(1) + ", " + t.get(2));
}
but I only get:
java.lang.IllegalStateException: Subquery cannot occur in select clause
How can I get a similar result?
where(criteriaBuilder.in(path). value(subquery)); TypedQuery<Object> typedQuery = entityManager. createQuery(select); List<Object> resultList = typedQuery. getResultList();
A subselect is a query embedded into another query. It's a powerful feature you probably know from SQL. Unfortunately, JPQL supports it only in the WHERE clause and not in the SELECT or FROM clause. Subqueries can return one or multiple records and can use the aliases defined in the outer query.
Advertisements. The Criteria API is a predefined API used to define queries for entities. It is the alternative way of defining a JPQL query. These queries are type-safe, and portable and easy to modify by changing the syntax.
It is supported in JPA 2.1 and Hibernate 5.0. You just had to add getSelection()
to the subquery argument in the multiselect
of the main query.
c.multiselect(item.get("id"),item.get("nome"), scount.getSelection());
Take a look at this working example:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<NotificationInfo> cq = builder.createQuery(NotificationInfo.class); //wrapper class
Root<Notification> n = cq.from(Notification.class); //root entity
//Subquery
Subquery<Long> sqSent = cq.subquery(Long.class);
Root<NotificationUser> sqSentNU = sqSent.from(NotificationUser.class);
sqSent.select(builder.count(sqSentNU));
sqSent.where(
builder.equal(sqSentNU.get(NotificationUser_.notification), n), //join subquery with main query
builder.isNotNull(sqSentNU.get(NotificationUser_.sendDate))
);
cq.select(
builder.construct(
NotificationInfo.class,
n.get(Notification_.idNotification),
n.get(Notification_.creationDate),
n.get(Notification_.suspendedDate),
n.get(Notification_.type),
n.get(Notification_.title),
n.get(Notification_.description),
sqSent.getSelection()
)
);
em.createQuery(cq).getResultList();
JPA does not support sub-queries in the select clause.
You need to either change your query so as not to use require the sub-query in the select clause, execute multiple queries, or use a native SQL query.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With