如何使用 QueryDsl 在查询中按 id 删除重复行

Posted

技术标签:

【中文标题】如何使用 QueryDsl 在查询中按 id 删除重复行【英文标题】:how to delete a repeat row by id in a query, using QueryDsl 【发布时间】:2021-03-11 09:09:57 【问题描述】:

我无法在查询中获取具有唯一行的查询 codeRecurrence。

public JPQLQuery<RecurrenceErrorVO> getQueryErrorRecurrence(Integer companyCode, Collection<SearchModelDTO<Object>> searchModelDTOs) 
    //Entities
    QRecurrencyEntity qRecurrencyEntity = QRecurrencyEntity.recurrencyEntity;
    QSubscriptionEntity qSubscriptionEntity = QSubscriptionEntity.subscriptionEntity;
    QRecurrencyDetailsEntity qRecurrencyDetailsEntity = QRecurrencyDetailsEntity.recurrencyDetailsEntity;
    QSubcriptionProductEntity qSubcriptionProductEntity = QSubcriptionProductEntity.subcriptionProductEntity;
    QArticleEntity qArticleEntity = QArticleEntity.articleEntity;
    QCatalogoValorDTO qStatusGeneral = new QCatalogoValorDTO("qStatusGeneral");
    QCatalogoValorDTO qrecurrenceType = new QCatalogoValorDTO("qrecurrenceType");
    QCatalogoValorDTO qbusinessTypeDTO = new QCatalogoValorDTO("qbusinessTypeDTO");
    QCatalogoValorDTO qcausalCatalogType = new QCatalogoValorDTO("qcausalCatalogType");
    //data
    JPQLQuery<RecurrenceErrorVO> query = from(qRecurrencyDetailsEntity).select(
            Projections.bean(RecurrenceErrorVO.class, qRecurrencyEntity.codeRecurrency.as("codeRecurrence"),
                    qRecurrencyDetailsEntity.codeDetailsTransaction.as("codeRecurrenceDetail"),
                    qRecurrencyEntity.statusGeneralValue.as("statusGeneralValue"),
                    qRecurrencyEntity.processDate.as("dateRecurrence"),
                    qRecurrencyDetailsEntity.transactionDate.as("dateTransaction"),
                    qSubscriptionEntity.contractIdentifier,
                    qSubcriptionProductEntity.articleEntity.itemDescription.as("productName"),
                    qSubscriptionEntity.numberDocumentClient.as("clientDocNumber"),
                    qSubscriptionEntity.customerName.as("clientName"),
                    qSubscriptionEntity.subscriptionValue.as("subscriptionValue"),
                    qSubscriptionEntity.statusSubscriptionValue,
                    qStatusGeneral.nombreCatalogoValor.as("statusGeneralDescription"),
                    qRecurrencyEntity.originRecurrenceValue.as("originRecurrenceValue"),
                    qRecurrencyEntity.value,
                    qRecurrencyEntity.status,
                    qRecurrencyDetailsEntity.causalValue.as("codeCausalValue"),
                    qRecurrencyDetailsEntity.causalType.as("codeCausalType"),
                    qbusinessTypeDTO.nombreCatalogoValor.as("marca"),
                    qcausalCatalogType.nombreCatalogoValor.as("causalValue"),
                    qrecurrenceType.nombreCorto.as("nombreCorto"),
                    qrecurrenceType.nombreCatalogoValor.as("transactionType")))
    //join
    query.leftJoin(qRecurrencyDetailsEntity.recurrencyEntity, qRecurrencyEntity)
            .leftJoin(qRecurrencyEntity.subscriptionEntity, qSubscriptionEntity)
            .leftJoin(qRecurrencyEntity.subcriptionProductEntity, qSubcriptionProductEntity)
            .innerJoin(qSubcriptionProductEntity.articleEntity, qArticleEntity)
            .innerJoin(qRecurrencyEntity.statusGeneral, qStatusGeneral)
            .innerJoin(qSubcriptionProductEntity.businessTypeDTO, qbusinessTypeDTO)
            .innerJoin(qRecurrencyDetailsEntity.recurrenceType, qrecurrenceType)
            .innerJoin(qRecurrencyDetailsEntity.causalCatalogType, qcausalCatalogType)
    ;
    BooleanBuilder where = new BooleanBuilder();
    where.and(qRecurrencyEntity.statusGeneralValue.ne(SirConstants.RECURRENCE_STATUS_FIN));
    where.and(qRecurrencyEntity.statusGeneralValue.ne(SirConstants.RECURRENCE_STATUS_SIN_CUPO));
    where.and(qRecurrencyEntity.statusGeneralValue.ne(SirConstants.RECURRENCE_STATUS_FIN_WITH_OBSERVATION));
    where.and(qRecurrencyDetailsEntity.statusRecurrencyDetailsValue.ne(SirConstants.ZERO.toString()));
    where.and(qRecurrencyEntity.originRecurrenceValue.eq(SirConstants.RECURRENCE_ORIGIN_INTERNO));
    where.and(qRecurrencyEntity.companyCode.eq(companyCode));
    where.and(qRecurrencyEntity.status.isTrue());
    SearchModelUtil.addDynamicWhere(searchModelDTOs, where, RecurrencyEntity.class, "recurrencyEntity");
    query.where(where);
    query.orderBy(qRecurrencyEntity.codeRecurrency.desc(), qRecurrencyDetailsEntity.codeDetailsTransaction.desc());
    return query;

这是我当前的代码, 这将返回值作为下一个表

CODERECURRENCY|CODEDCURRENCYDETAILS|STATUSGENERALVALUE|PROCESSDATE        |TRANSACTIONDATE    
--------------|--------------------|------------------|-------------------|-------------------
         16202|               14510|ERR               |2020-10-23 12:08:26|2020-11-27 16:53:57
         16202|               14094|ERR               |2020-10-23 12:08:26|2020-10-23 12:08:47
         16202|               14093|ERR               |2020-10-23 12:08:26|2020-10-23 12:08:41
         16201|               14088|EXR               |2020-10-22 23:51:58|2020-10-22 23:53:43
         16201|               14087|EXR               |2020-10-22 23:51:58|2020-10-22 23:53:37
         16201|               14083|EXR               |2020-10-22 23:51:58|2020-10-22 23:53:15
         16201|               14082|EXR               |2020-10-22 23:51:58|2020-10-22 23:53:09
         16201|               14078|EXR               |2020-10-22 23:51:58|2020-10-22 23:52:47
         16201|               14077|EXR               |2020-10-22 23:51:58|2020-10-22 23:52:41
         16201|               14073|EXR               |2020-10-22 23:51:58|2020-10-22 23:52:19
         16201|               14072|EXR               |2020-10-22 23:51:58|2020-10-22 23:52:13
         16123|               13675|ERR               |2020-10-01 17:06:17|2020-10-01 17:06:28
         16050|               13511|ERR               |2020-09-21 14:11:31|2020-09-21 14:11:31
         16043|               13470|EXR               |2020-09-16 10:04:20|2020-09-16 10:07:00

codeRecurrency 需要一行一行,我使用代码删除重复行,但如果我将 JpqlQuery 转换为列表并且这会更改 web 服务中显示的值的结果,我需要使用分页。

这段代码展示了查询的用法。

private PageResultVO<RecurrenceErrorVO> findPagedRE(JPQLQuery<RecurrenceErrorVO> query, Pageable pageable) 
        List<RecurrenceErrorVO> list = Objects.requireNonNull(getQuerydsl()).applyPagination(
                pageable, query).fetch();
          Page<RecurrenceErrorVO> page = PageableExecutionUtils.getPage(list,
                pageable,
                query::fetchCount);
        return new PageResultVO<>(page.getContent(), page.getPageable(), page.getTotalElements());
    

我将此代码用于将来作为带有分页的 Web 服务公开。

我该怎么办?

【问题讨论】:

【参考方案1】:

您需要使用带有 group by 子句的聚合函数(不能与 JPA 的 QueryDSL 中的 query::fetchCount 一起使用)或带有窗口函数的不同元组(需要注册自定义函数)。即使这样,您也可能会在投影中遇到实体投影。例如,您不能使用MAX(someEntity) 来获取具有MAX(someEntity.id) 的实体。

使用普通的 Hibernate 和 QueryDSL 无法做到这一点,但可以使用 Blaze-Persistence integration for QueryDSL 完成。使用这个 Hibernate 扩展,您可以使用窗口函数或在指定GROUP BYHAVING 子句的查询中使用fetchCount。您还可以利用 Blaze-Persistence CTE 或子查询横向连接来创建查询。

【讨论】:

我最后在数据库中使用了一个视图,并为该视图创建了一个新实体并获取存储库中的工作数据,我将检查 Blaze-persistence 以获取您的答案。 是的,有时视图映射到原生查询实际上是最简单的。我也时不时求助于他们!

以上是关于如何使用 QueryDsl 在查询中按 id 删除重复行的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flask-SQLAlchemy 中按 id 删除记录

如何使用 QueryDSL 在查询中使用 SAMPLE 关键字

如何在没有域类的 querydsl 中构造查询

如何在 Querydsl 中创建子查询

如何以简洁的方式在Datastax DSE 5.0 Graph中按顶点ID查询?

如何从querydsl获得完全物化的查询