有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有行数窗口函数的java QueryDSL 4

我正在使用带有spring数据的查询dsl

环境:

    <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>

查询:

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();

例外情况:

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]

查询DSL文档:http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s03.html#d0e1276

其他堆栈溢出问题:QueryDSL Window functions

有什么建议吗


共 (2) 个答案

  1. # 1 楼答案

    抱歉迟到了,但我也遇到了同样的问题,我通过从there添加配置文件解决了这个问题

    然后注入CriteriaBuilderFactory

     @Inject
    CriteriaBuilderFactory cbf; 
    

    在开始时,然后用窗口函数编写任何查询,如下所示

    QProductHistory his =QProductHistory.productHistory;
    SimpleExpression<Long> rown =  JPQLNextExpressions.rowNumber().over().partitionBy(his.esn).as("rown");
    BlazeJPAQuery<Tuple> bl_qry = new BlazeJPAQuery<Tuple>(entityManager, cbf).from(his)
                .select(his.esn, rown);
    
        List<Tuple> fetch = bl_qry.fetch();
    
  2. # 2 楼答案

    窗口函数不包括在JPQL规范中,因此在任何JPA实现中都不可用。您可以使用custom functions自己注册这些函数

    然而,在此之后,这些函数仍然无法在QueryDSL中访问。您正在从这里的SQLExpressions中获取一个窗口表达式。这些方法存在于SQLExpressions中是有原因的:它们只与querydsl-sql一起工作,而不与querydsl-jpa一起工作(同样,因为JPA本身不支持窗口函数)。因此,在注册自定义函数之后,您仍然需要扩展JPQLTemplates以包含自定义窗口函数的模板

    你会这样做:

    public class MyTemplates extends JPQLTemplates {
    
        public MyTemplates() {
            add(SQLOps.ROWNUMBER, "ROW_NUMBER({0})");
        }
    
    }
    

    然后按如下方式使用:

    new JPAQuery(entityManager, new MyTemplates()).from(entity).select(rowNumber())
    

    在中间使用Spring集成,模板比我想的查询更难绑定。p>


    或者,您可以研究^{}扩展,它对JPQL的窗口函数(以及许多其他特性)提供了现成的支持。例如:

    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();