Closed guofengzh closed 3 weeks ago
Remind: This issue can also be repoduced using com.querydsl 5.0 and 5.1, see the branch com.querydsl-5.x.
By the way, Blaze Persistence is excellent, but it uses string constants to reference the attributes of entities and associations, which is not type-safe and is not convenient for refactoring attribute names in IDE tools.
So, I'd like to ask here as well, Querydsl uses Q classes to support type-safe access to entity attributes (for example, QCat.cat.name), and uses "new QCat("ketty)" to specify the alias. Does Blaze Persistence have similar functionality (I'm new to Blaze Persistence)?
Although it does seem not many changes are required to make EntityViews work with the Querydsl integrations, currently this is not implemented (https://github.com/Blazebit/blaze-persistence/issues/1644). Also note that casing to CriteriaBuilder
is not safe for set operations and queries with common table expressions.
Does Blaze Persistence have similar functionality (I'm new to Blaze Persistence)?
It does not yet, but I had some ideas on how to approach this:
All these ideas require the a custom static metamodel which means writing a custom annotation processor. It's doable, but nobody stepped up yet to do the work.
I'm touched that you responded so quickly.
I tried that using the followin Querydsl query can solve the issue. The simple test wroks.
...
.select(cat.id, cat.name)
...
But I tried a lot and failed to write a select clause for the following view:
@EntityView(Person.class)
public interface PersonView {
@IdMapping
Long getId();
String getName();
List<CatSimpleView> getKittens();
}
By the way, the code listed in 21.8. Recursive CTEs does not work with mysql 8.2 (It works with H2). See the test case at QuerydslCTETest#recursiveCTETest1. The thrown exception is
org.hibernate.exception.GenericJDBCException: JDBC exception executing SQL [with recursive CatCte(id, name, ancestor_id) AS( select c1_0.id,c1_0.name,c1_0.ancestor_id from cat c1_0 where c1_0.id=? UNION ALL select c1_0.id,c1_0.name,c1_0.ancestor_id from cat c1_0,CatCte cc1_0,CatCte cc2_0 where c1_0.id=cc2_0.ancestor_id ) select cc1_0.id,cc1_0.ancestor_id,cc1_0.name from CatCte cc1_0] [In recursive query block of Recursive Common Table Expression 'catcte', the recursive table must be referenced only once, and not in any subquery] [n/a]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:63)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:94)
at org.hibernate.sql.results.jdbc.internal.DeferredResultSetAccess.executeQuery(DeferredResultSetAccess.java:264)
at org.hibernate.sql.results.jdbc.internal.DeferredResultSetAccess.getResultSet(DeferredResultSetAccess.java:167)
at org.hibernate.sql.results.jdbc.internal.JdbcValuesResultSetImpl.advanceNext(JdbcValuesResultSetImpl.java:265)
at org.hibernate.sql.results.jdbc.internal.JdbcValuesResultSetImpl.processNext(JdbcValuesResultSetImpl.java:145)
at org.hibernate.sql.results.jdbc.internal.AbstractJdbcValues.next(AbstractJdbcValues.java:19)
at org.hibernate.sql.results.internal.RowProcessingStateStandardImpl.next(RowProcessingStateStandardImpl.java:67)
at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:182)
at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:33)
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:211)
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:83)
at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:76)
at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:65)
at com.blazebit.persistence.integration.hibernate.base.HibernateExtendedQuerySupport.getResultList(HibernateExtendedQuerySupport.java:591)
at com.blazebit.persistence.integration.hibernate.base.HibernateExtendedQuerySupport.getResultList(HibernateExtendedQuerySupport.java:503)
at com.blazebit.persistence.impl.plan.CustomSelectQueryPlan.getResultList(CustomSelectQueryPlan.java:58)
at com.blazebit.persistence.impl.query.CustomSQLTypedQuery.getResultList(CustomSQLTypedQuery.java:53)
at com.querydsl.jpa.impl.AbstractJPAQuery.getResultList(AbstractJPAQuery.java:195)
at com.querydsl.jpa.impl.AbstractJPAQuery.fetch(AbstractJPAQuery.java:247)
at com.avic.querydsl.QuerydslCTETest.recursiveCTETest1(QuerydslCTETest.java:73)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.sql.SQLException: In recursive query block of Recursive Common Table Expression 'catcte', the recursive table must be referenced only once, and not in any subquery
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:130)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:972)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)
at org.hibernate.sql.results.jdbc.internal.DeferredResultSetAccess.executeQuery(DeferredResultSetAccess.java:246)
... 21 more
The sql generated by Hibernate is:
with recursive CatCte(id, name, ancestor_id) AS
(
select c1_0.id,c1_0.name,c1_0.ancestor_id from cat c1_0 where c1_0.id=?
UNION ALL
select c1_0.id,c1_0.name,c1_0.ancestor_id from cat c1_0,CatCte cc1_0,CatCte cc2_0 where c1_0.id=cc2_0.ancestor_id
)
select cc1_0.id,cc1_0.ancestor_id,cc1_0.name from CatCte cc1_0
CatCte cc1_0
following UNION ALL
may be redundant.
The code list in 14.2. Recursive CTEs works, but the following code must be changed from
.where("id").eqExpression("parentCat.ancestor.id") (3)
to
.where("cat.id").eqExpression("parentCat.ancestor.id") (3)
or the following exception is thrown:
java.lang.IllegalArgumentException: Could not join path [id] because it did not use an absolute path but multiple root nodes are available!
Thanks for your help very much.
The documentation is part of the repository. We would very much appreciate a PR that fixes this.
I have created the pull request 1943.
Thanks for your helps!
Thank you!
Description
I tried to use the entity view to project a Querydsl query as described in Querydsl integration. This is the code:
Expected behavior
The SQL generated by Hibernate should be
and the query result shoud be something like
Actual behavior
The SQl generated is
please note that it selects all the columns of the Cat entity, and not make the projection.
then throws the exception:
I debug the generated source code CatSimpleViewImpl.java.
noop = null offset = 0 tuple.length is 3 tuple[0] = Cat@13462 (a Cat instance) tuple[1] = 1 tuple[2] = 'Tom'
Steps to reproduce
Clone blaze-querydsl-demo, then run
Environment
Version: 1.6.12 JPA-Provider: Hibernate 6.5.2.Final Spring Boot: 3.3.2 DBMS: H2 2.2.224 Querydsl: 6.7, OpenFeign fork JDK: Oracle Java SE 21