I'm using query dsl with spring data.
Environment:
<querydsl-apt.version>4.1.4</querydsl-apt.version>
<querydsl-jpa.version>4.1.4</querydsl-jpa.version>
<querydsl-sql.version>4.1.4</querydsl-sql.version>
<spring>4.3.3.RELEASE</spring>
Query:
JPAQueryFactory query = new JPAQueryFactory(getEntityManager());
SimpleExpression<Long> rowNumber = SQLExpressions.rowNumber()
.over()
.orderBy(qServiceExecution.updatedAt.asc()).as("rowNumber");
List<Tuple> response = query.select(qServiceExecution.id, SQLExpressions.rowNumber()
.over()
.orderBy(qServiceExecution.updatedAt.asc()))
.from(qServiceExecution)
.fetch();
Exception:
Root cause: java.lang.IllegalArgumentException: No pattern found for ROWNUMBER
at com.querydsl.core.support.SerializerBase.visitOperation(SerializerBase.java:280) ~[querydsl-core-4.1.4.jar:na]
at com.querydsl.jpa.JPQLSerializer.visitOperation(JPQLSerializer.java:437) ~[querydsl-jpa-4.1.4.jar:na]
at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:231) ~[querydsl-core-4.1.4.jar:na]
at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:31) ~[querydsl-core-4.1.4.jar:na]
Spring error: No pattern found for ROWNUMBER; nested exception is java.lang.IllegalArgumentException: No pattern found for ROWNUMBER
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:384) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:491) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE]
Query DSL documentation: http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s03.html#d0e1276
Other stack overflow question: QueryDSL Window functions
Any suggestion?
Window functions are not included in the JPQL specification and as such not available in any JPA implementation. You could register these functions yourself using custom functions.
However, after this, these functions still won't be accessible in QueryDSL. You're stealing from the SQLExpressions
here to obtain a window expression. These methods live in SQLExpressions
for a reason: they only work with querydsl-sql
and not with querydsl-jpa
(again, because JPA itself does not support window functions). So after registering your custom function, you will still have to extend JPQLTemplates
to include the template for your custom window function.
You'd do this like this:
public class MyTemplates extends JPQLTemplates {
public MyTemplates() {
add(SQLOps.ROWNUMBER, "ROW_NUMBER({0})");
}
}
And then use it as follows:
new JPAQuery(entityManager, new MyTemplates()).from(entity).select(rowNumber())
With the Spring integration in the middle however, the templates are somewhat more difficult to bind to the query I think.
Alternatively you could look into the blaze-persistence-querydsl
extension, which has out of the box support for window functions (and many other features) for JPQL. For example:
QCat cat = QCat.cat;
BlazeJPAQuery<Tuple> query = new BlazeJPAQuery<Tuple>(entityManager, criteriaBuilderFactory).from(cat)
.select(cat.name, JPQLNextExpressions.rowNumber(), JPQLNextExpressions.lastValue(cat.name).over().partitionBy(cat.id));
List<Tuple> fetch = query.fetch();
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