How to use listagg with querydsl?

怎甘沉沦 提交于 2020-12-27 05:38:31

问题


I have a query as shown below;

SELECT 
   .
   .
   LISTAGG(DISTINCT CC.POPULATION, ', ') WITHIN GROUP (ORDER BY CC.POPULATION ASC),
   .
   .
FROM COUNTRY C
     JOIN CITY CC ON C.ID = CC.COUNTRY_ID
--WHERE 
GROUP BY C.ID;

I should be implement with querydsl for custom filtering and sorting operations but I got "No pattern found for LISTAGG" error

JPAQuery<Tuple> jpaQuery = jpaQueryFactory.select(         
            SQLExpressions.listagg(QCity.city.POPULATION, ",")
            .withinGroup()
            .orderBy(QCity.city.POPULATION.asc())
    )
            .from(QCountry.country)
            .join(QCity.city).on(QCountry.country.id.eq(QCity.city.countryId))
            //.where(custom filtering)
            .groupBy(QCountry.country.id);

jpaQuery.fetch();

I try to add custom template like this but I couldn't succeed. Also my querydsl-sql version is 4.2.1

StringTemplate customPopulationTemplate = Expressions.stringTemplate(
            "(LISTAGG(DISTINCT {0},',') WITHIN GROUP (ORDER BY {0} ASC))", QCity.city.population);

回答1:


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

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


来源:https://stackoverflow.com/questions/65378623/how-to-use-listagg-with-querydsl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!