如何正确地使用fetch或fetchresults在querydsl查询中获取页面作为结果?

ergxz8rk  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(901)

嗨,我想在这里实现的是,我想将可分页数据提交到querydsl查询中,并将结果作为页面,我如何才能正确地完成它?以下是我到目前为止所做的:
这是我的控制器:

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

在我的控制器中,我提交StockViewByProductCodesTo,如下所示:

@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(请求)提取可分页信息,下面是我的pageableutils函数:

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

}

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

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

在我的编辑器中,当查看我的存储库并且我能够运行我的项目时,没有任何错误,但是当我执行存储库功能时,出现以下错误:
“org.hibernate.hql.internal.ast.querysyntaxexception:应为close,found,','靠近第1行第38列[选择计数(distinct 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和stock.productcode在?2中,stock.branchcode=?3和stock.branchid=?4];嵌套的异常是java.lang.illegalargumentexception:org.hibernate.hql.internal.ast.querysyntaxexception:expecting close,found',靠近第1行第38列[选择count(distinct 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和stock.productcode在?2中,stock.branchcode=?3和stock.branchid=?4]“
问题就在这里,在这条线上:

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

当我执行那一行时,它会给我这个错误,我试图得到fetchresult,因为我想得到总数的.gettotal()。
但是如果我用.fetch()执行查询,它工作得很好,如下所示:

List<StockAkhirResponseDto> stockAkhirDto = query.fetch()

我得到了正确执行的sql结果,这里遗漏了什么?如何正确获取页面结果?

nbysray5

nbysray51#

您的问题可能与未解决的querydsl问题有关。文件化的问题与 fetchCount 但我想很可能也是你的情况。
在上述问题上考虑以下评论: fetchCount() 使用 COUNT 函数,它是一个聚合函数。您的查询已具有聚合函数。除非使用子查询(在jpa中不可用),否则不能聚合函数。因此不能支持这个用例。
这个问题也提供了一个临时解决办法。
基本上,这个想法是能够执行 COUNT 通过在初始select上创建语句。afaik使用querydsl是不可能的,这就是为什么在指定的解决方法中他们访问hibernate提供的下划线机制。
也许,您可以尝试避免这种限制的另一件事是为查询创建一个数据库视图,在其上创建相应的querydsl对象,并使用这些对象来执行实际的计算。我知道这不是一个理想的解决方案,但它将绕过当前querydsl的限制。

相关问题