Querydsl: How to write subquery for QueryDSL version 4.2.1?

Created on 19 Jul 2019  路  11Comments  路  Source: querydsl/querydsl

We are using QueryDSL version 4.2.1 on spring-boot project and we need to write subquery.

But all the example we found use SimpleSubQuery or JPASubQuery.

Neither of these 2 classes could be found in version 4.2.1.

Could you please suggest me how to write subquery for QueryDSL version 4.2.1?

question

Most helpful comment

I think the best practice is:

JPQLQuery<Long> subQuery=JPAExpressions.select(QEntity.entity.id).where(somePredicate);
queryFactory.selectFrom(..something).where(QOtherEntity.otherEntity.id.in(subQuery);

All 11 comments

What artifacts are you using? Are you using querydsl-sql or querydsl-jpa? querydsl-jpa definitely has JPASubQuery.

I think the best practice is:

JPQLQuery<Long> subQuery=JPAExpressions.select(QEntity.entity.id).where(somePredicate);
queryFactory.selectFrom(..something).where(QOtherEntity.otherEntity.id.in(subQuery);

image

@kartoffelsup Thank you for your feedback. Please refer to above image.

I'm using VisualCode, with plugin for Java, but it does not show any suggest for those classes.

Other basic query like below is OK

JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QCustomer customer = QCustomer.customer;
QCompany company = QCompany.company;
List<Tuple> result = queryFactory.select(
customer.name,
customer.id,
company.name,
company.id
)
.from(customer)
.innerJoin(customer.company, company)
.fetch();

This is my subquery which I am using and failed to compile:

SimpleSubQuery<Customer> mostPopularRaceSubquery = new JPASubQuery().from(customer).join(company).groupBy(company);

I'm using querydsl-jpa

image

I think the best practice is:

JPQLQuery<Long> subQuery=JPAExpressions.select(QEntity.entity.id).where(somePredicate);
queryFactory.selectFrom(..something).where(QOtherEntity.otherEntity.id.in(subQuery);

Thank you @thackel for your reply.

From what you provided, I'm able to create the query, but in runtime, I got Exception:

The code is as below:

image

Below is the exception:

DEBUG com.querydsl.jpa.impl.JPAQuery - select customer from Customer customer where customer.company.id in (select company.id where company.id = ?1)
ERROR org.hibernate.hql.internal.ast.ErrorCounter - <AST>:0:0: unexpected end of subtree
ERROR org.hibernate.hql.internal.ast.ErrorCounter - <AST>:0:0: unexpected end of subtree
antlr.NoViableAltException: unexpected end of subtree
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3600) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]

I realized one thing, the subquery does not have "FROM" but I don't know how to fix

image

@datntvn you are missing the "from" part in the subquery. I missed it in my example.

JPAExpressions.select(QEntity.entity.id).from(QEntity.entity).where(somePredicate);

But this kind of simple query i would express by a join not a subselect.

@thackel After added "FROM", the query seemed to work.
image

I tested the console's output SQL and it return data
image

But I get another runtime Exception as
nested exception is com.querydsl.core.NonUniqueResultException: javax.persistence.NonUniqueResultException: query did not return a unique result: 2] with root cause
javax.persistence.NonUniqueResultException: query did not return a unique result: 2
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:123) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]

I think it's because the returned data is 2 records. How could I handle the queried result properly in this case?

Thank you so much for your help.

P/S: I prepared this simple query with QueryDSL in order for a more complicated scenario.

@thackel I'm able to do it.

I replaced fetchOne with fetch

image

@kartoffelsup Although I am able to create subquery, please keep this as open because I still cannot use SimpleSubQuery and JPASubQuery for version 4.2.1

You are expecting just one result by adding .fetchOne(). Just use .fetch() and get a list of possible results.

You are expecting just one result by adding .fetchOne(). Just use .fetch() and get a list of possible results.

I'm totally new to QueryDSL and I don't know what is what. I'm on the learning process.

@kartoffelsup Although I am able to create subquery, please keep this as open because I still cannot use SimpleSubQuery and JPASubQuery for version 4.2.1

Yes, you can't use them because they are not public api. Sorry, didn't see that before, just checked if the classes existed. The way that @thackel subscribed seems to be the proper way of doing subqueries in querydsl.

p.s. I'm not a querydsl maintainer so I can't close the issue anyway ;)

@thackel already answered this. It is very intentional that JPASubQuery and SimpleSubQuery cannot be used anymore.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jmpicnic picture jmpicnic  路  7Comments

svaidya401 picture svaidya401  路  4Comments

robertandrewbain picture robertandrewbain  路  5Comments

beamofsoul picture beamofsoul  路  6Comments

okihouse picture okihouse  路  5Comments