javaspringjpqlquerydslpageable

how to delete a repeat row by id in a query, using QueryDsl


I'm stuck in get the query with unique row for codeRecurrence in a query.

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

this is my current code, and this returns values ​​as the next table

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

Need one a row by codeRecurrency, I used code for remove the repeats rows, but works if i convert JpqlQuery to a list and this change the result of values show in the webservice, i need use pagination.

this code shows the use of the query.

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

I use this code for future exposure as webservice with pagination.

What I should do?


Solution

  • You would need to use either aggregate functions with a group by clause (which cannot be used in conjunction with query::fetchCount in QueryDSL for JPA) or a distinct tuple with window functions (which requires custom functions to be registered). And even then you probably struggle with the entity projections in your projection. For example, you can't do MAX(someEntity) to get the entity with MAX(someEntity.id).

    With plain Hibernate and QueryDSL this cannot be done, but it can be done using the Blaze-Persistence integration for QueryDSL. Using this Hibernate extension you can use window functions or use fetchCount in queries that specify a GROUP BY or HAVING clause. You could also utilise Blaze-Persistence CTE's or subquery lateral joins to create the query.