繁体   English   中英

如何使用 fetch 或 fetchResults 正确获取 Page 作为 Querydsl 查询的结果?

[英]How to get Page as result in Querydsl query with fetch or fetchResults properly?

嗨,我想在这里实现的是,我想将 Pageable 数据提交到 QueryDsl 查询中并将结果作为 Page,我该如何正确地做到这一点? 这是我到目前为止所做的:

这是我的 controller:

@PostMapping("/view-latest-stock-by-product-codes")
public ResponseEntity<RequestResponseDTO<Page<StockAkhirResponseDto>>> findStockByProductCodes(
        @RequestBody StockViewByProductCodesDto request) {

    Page<StockAkhirResponseDto> stockAkhir = stockService.findByBulkProduct(request);

    return ResponseEntity.ok(new RequestResponseDTO<>(PESAN_TAMPIL_BERHASIL, stockAkhir));
}

在我的 controller 我提交 StockViewByProductCodesDto 看起来像这样:

@Data
public class StockViewByProductCodesDto implements Serializable {

    private static final long serialVersionUID = -2530161364843162467L;

    @Schema(description = "Kode gudang yang ingin di tampilkan", example = "GBKTJKT1", required = true)
    private String warehouseCode;

    @Schema(description = "id dari sebuah branch", example = "1", required = true)
    private Long branchId;

    @Schema(description = "Kode Branch", example = "JKT", required = true)
    private String branchCode;

    @Schema(description = "Kode Product yang merupakan kode yang di ambil dari master product", example = "[\"MCM-508\",\"TL-101\"]", required = true)
    private List<String> productCodes;

    @Schema(description = "Size of row per page", example = "15", required = true)
    @NotNull
    private int size;

    @Schema(description = "Page number", example = "1", required = true)
    @NotNull
    private int page;

    @Schema(description = "Sort by", example = "id", required = false)
    private String sort;
}

这是我的服务:

public Page<StockAkhirResponseDto> findByBulkProduct(StockViewByProductCodesDto request) {
    String warehouseCode = request.getWarehouseCode();
    Long branchId = request.getBranchId();
    String branchCode = request.getBranchCode();
    List<String> productCodes = request.getProductCodes();
    Set<String> productCodesSet = new HashSet<String>(productCodes);

    Pageable pageable = PageUtils.pageableUtils(request);

    Page<StockAkhirResponseDto> stockAkhir = iStockQdslRepository.findBulkStockAkhirPage(warehouseCode, branchId, branchCode, productCodesSet, pageable);

    return stockAkhir;
}

如您所见,我使用 PageUtils.pageableUtils(request) 提取可分页信息,这是我的 pageableUtils function 看起来像:

public static Pageable pageableUtils(RequestKeyword request) {
    int page = 0;
    int size = 20;

    if (request.getPage() > 0) {
        page = request.getPage() - 1;
    }

    if (request.getSize() > 0) {
        size = request.getSize();
    }

    if (!request.getSort().isEmpty()) {
        return PageRequest.of(page, size, Sort.by(request.getSort()).descending());
    } else {
        return PageRequest.of(page, size);
    }
    
}

获得 Pageable 数据后,我将其提交到我的存储库中,如下所示:

public Page<StockAkhirResponseDto> findBulkStockAkhirPage(String warehouseCode, Long branchId, String branchCode,
                                                      Set<String> productCodes, Pageable pageable) {

    JPQLQuery<Tuple> query = new JPAQuery<>(em);

    long offset = pageable.getOffset();
    long limit = pageable.getPageSize();

    QStock qStock = QStock.stock;
    NumberExpression<Integer> totalQty = qStock.qty.sum().intValue();
    query = query.select(qStock.productId, qStock.productCode, totalQty).from(qStock)
            .where(qStock.warehouseCode.eq(warehouseCode), qStock.productCode.in(productCodes),
                    qStock.branchCode.eq(branchCode), qStock.branchId.eq(branchId))
            .groupBy(qStock.productId, qStock.productCode);

    query.limit(limit);
    query.offset(offset);
    QueryResults<Tuple> result = query.fetchResults();
    long total = result.getTotal();
    List<Tuple> rows = result.getResults();

    List<StockAkhirResponseDto> stockAkhirDto = rows.stream()
            .map(t -> new StockAkhirResponseDto(t.get(0, Long.class), t.get(1, String.class), t.get(2, Integer.class)))
            .collect(Collectors.toList());

    return new PageImpl<>(stockAkhirDto, pageable, total);
}

查看我的存储库并且我能够运行我的项目时,我的编辑器中没有错误,但是当我执行我的存储库 function 时,我收到了这个错误:

“org.hibernate.hql.internal.ast.QuerySyntaxException:期待关闭,在第 1 行,第 38 列附近找到',' [选择计数(不同的 stock.productId,stock.productCode,stock.warehouseId,stock.warehouseCode,stock.branchCode , stock.branchId)\n来自 com.bit.microservices.b2b.warehouse.entity.Stock stock\n其中 stock.warehouseCode =?1 and stock.productCode in?2 and stock.branchCode =?3 and stock.branchId =?4 ]; 嵌套异常是 java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: 期待 CLOSE,在第 1 行,第 38 列附近找到',' .warehouseId、stock.warehouseCode、stock.branchCode、stock.branchId)\n来自 com.bit.microservices.b2b.warehouse.entity.Stock stock\n其中 stock.warehouseCode =?1 和 stock.productCode in?2 和 stock.branchCode =?3 和 stock.branch ID =?4]"

问题就在这里,在这一行:

QueryResults<Tuple> result = query.fetchResults();

当我执行该行时,它给了我该错误,我尝试获取 fetchResult,因为我想获取总数的 .getTotal()。

但如果我使用.fetch() 执行查询,它工作正常,如下所示:

List<StockAkhirResponseDto> stockAkhirDto = query.fetch()

我的 sql 结果正确执行,我在这里错过了什么? 我如何正确获得页面结果?

您的问题可能与开放的 QueryDSL问题有关。 记录的问题与fetchCount的使用有关,但我认为很可能也是您的情况。

考虑上述问题中的以下评论

fetchCount()使用一个COUNT function,它是一个聚合 function。 您的查询已经具有聚合函数。 您不能聚合聚合函数,除非使用子查询(在 JPA 中不可用)。 因此,无法支持此用例。

该问题也提供了一个临时解决方案

基本上,这个想法是能够通过在初始 select 上创建一个语句来执行COUNT AFAIK QueryDsl 不可能,这就是为什么在指定的解决方法中他们访问 Hibernate 提供的下划线机制。

也许,您可以尝试避免限制的另一件事是为您的查询创建一个数据库视图,在其上创建相应的 QueryDsl 对象,并使用这些对象执行实际计算。 我知道这不是一个理想的解决方案,但它会绕过这个当前的 QueryDsl 限制。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM