首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用listagg和querydsl?

如何使用listagg和querydsl?
EN

Stack Overflow用户
提问于 2020-12-20 09:44:17
回答 2查看 1.2K关注 0票数 0

我有如下所示的查询;

代码语言:javascript
复制
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;

我应该使用querydsl实现自定义过滤和排序操作,但是我得到了“LISTAGG找不到模式”错误

代码语言:javascript
复制
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();

我试图添加这样的自定义模板,但我无法成功。我的querydsl-sql版本也是4.2.1。

代码语言:javascript
复制
StringTemplate customPopulationTemplate = Expressions.stringTemplate(
            "(LISTAGG(DISTINCT {0},',') WITHIN GROUP (ORDER BY {0} ASC))", QCity.city.population);
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-27 23:39:08

由于Hibernate 5.2.18,即使您是通过JPA引导,也可以使用MetadataBuilderContributor实用程序自定义MetadataBuilder。

MetadataBuilderContributor接口可以这样实现:

代码语言:javascript
复制
public class SqlFunctionsMetadataBuilderContributor
    implements MetadataBuilderContributor {
     
 @Override
 public void contribute(MetadataBuilder metadataBuilder) {
    metadataBuilder.applySqlFunction(
        "group_concat",
        new StandardSQLFunction(
            "group_concat",
            StandardBasicTypes.STRING
        )
    );
 }
}

而且,我们可以通过SqlFunctionsMetadataBuilderContributor配置属性提供hibernate.metadata_builder_contributor:

代码语言:javascript
复制
<property>
    name="hibernate.metadata_builder_contributor"
    value="com.vladmihalcea.book.hpjp.hibernate.query.function.SqlFunctionsMetadataBuilderContributor"
</property>

参考资料:https://vladmihalcea.com/hibernate-sql-function-jpql-criteria-api-query/

票数 0
EN

Stack Overflow用户

发布于 2020-12-20 13:46:15

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

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

你会这样做的:

代码语言:javascript
复制
public class MyTemplates extends JPQLTemplates {

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

}

然后按以下方式使用:

代码语言:javascript
复制
new JPAQuery(entityManager, new MyTemplates()).from(entity).select(rowNumber())

或者,您可以查看blaze-persistence-querydsl扩展,它对JPQL的窗口函数(和许多其他特性)提供了开箱即用的支持。例如:

代码语言:javascript
复制
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();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65378623

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档