I am trying to create a BlazeJPAQuery with a select from a subquery, but I'm running into issues with CTE and received the following error:
java.lang.UnsupportedOperationException: Select statement should be bound to any CTE attribute
I currently have a subquery that looks something like this:
BlazeJPAQuery<Author> subQuery = getBlazeJPAQuery()
.select(QAuthor.author)
.from(getQueryForBooks(), QBook.book)
.innerJoin(QAuthor.author).on(QAuthor.author.key.eq(QBook.book.author.key));
The subquery works just fine if I'm fetching directly from it, but I need to expand upon this and do extra filtering in the future. That is why I'm trying to encapsulate the subquery with another query that will eventually have its own where-clause. Let me show you what I mean.
var superQuery = getBlazeJPAQuery()
.select(QAuthor.author);
.from(subQuery, QAuthor.author)
If I execute my superQuery I get the aforementioned exception. I have tried instantiating QAuthor and QBook with what I assume is the alias as the contructor parameter (even though it's named 'variable' inside the Q-classes). I assume the exception happens because Blaze Persistence has a hard time telling the difference between the elements in the select and the elements in the from as both are QAuthor. There is not much documentation on blazebit for QueryDSL extention. But I did find the part about subquery joins under the QueryDSL section that mentions that I have to bind attributes when using CTE.
Here is the snippet:
Subquery joins utilize Common Table Expressions. Therefore also CTE types are allowed for subquery results. In that case, the CTE attributes should be bound in a similar fashion as shown in the CTE examples. Whenever the subquery projects an entity path that is also a join target, all owned attributes will be bound implicitly if no different bindings are provided.
Here is one example where I tried to instantiate QAuthor to follow the example they gave on their documentation. But it doesn't work.
var author = new QAuthor("myAuthor");
var superQuery = getBlazeJPAQuery()
.select(author);
.from(subQuery, author)
Can someone point me in the right direction. Here is the example they give on how to use subqueries.
QRecursiveEntity recursiveEntity = new QRecursiveEntity("t");
List<Author> fetch = new BlazeJPAQuery<>(entityManager, cbf)
.select(author)
.from(select(author)
.from(author)
.orderBy(author.name.asc())
.limit(1L), recursiveEntity)
.fetch();
I don't understand why they are providing a new type for their where-clause, namely the QRecursiveEntity. Maybe that's what I'm missing.
Blaze-Persistence implements support for subqueries in the FROM clause by using a special @CTE
entity as type for the subquery. You have to map your subquery to the attributes of this special entity and Blaze-Persistence will ensure the query is built in a way so that Hibernate ORM can see it as if it were an entity.
If you just want to push some filtering into a subquery but select the whole entity, you can avoid the separate CTE entity. Also take a look into the testsuite code that exercises the API.