You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blaze-Persistence Querydsl是否支持投影?如何使用并解决where空指针问题

Blaze-Persistence Querydsl集成相关问题解答

1. Projections支持性确认

Blaze-Persistence与Querydsl的集成完全支持Projections,覆盖接口投影、DTO类投影、元组投影、构造器投影等所有常用投影类型,同时兼容Blaze-Persistence原生的CTE、子查询、多表关联等特性,不会因为复杂查询场景限制投影功能的使用。

2. Blaze-Persistence Querydsl中Projections的使用方式

常用的使用方式有两种:

  • 字段映射投影:直接在cbf.create方法中指定返回的DTO类,查询时select语句的别名与DTO类的字段名保持完全一致,Blaze-Persistence会自动完成字段映射赋值,你当前的代码写法就属于这类方式。
  • Querydsl构造器投影:借助Querydsl原生的Projections.constructor方法,直接绑定DTO类的构造参数完成映射,示例代码如下:
// 基于Querydsl Q类的构造器投影示例
List<WalletReportDto> result = new BlazeJPAQuery<WalletReportDto>(em, cbf)
    .from(QTenantBalanceOffers.tenantBalanceOffers, "tbo")
    .innerJoin(QTenantWallet.tenantWallet)
    .on(QTenantBalanceOffers.tenantBalanceOffers.wallet.id.eq(QTenantWallet.tenantWallet.id))
    .groupBy(QTenantWallet.tenantWallet.id)
    .select(Projections.constructor(WalletReportDto.class,
        QTenantWallet.tenantWallet.createdDate.min().as("fromDate"),
        QTenantWallet.tenantWallet.createdDate.max().as("toDate"),
        QTenantWallet.tenantWallet.customer.email.as("email"),
        QTenantBalanceOffers.tenantBalanceOffers.amount.sum().as("totalAmount")
    ))
    .fetch();

3. 空指针问题修复方案

你遇到的criteria.getEmail()触发空指针的核心原因是:当criteria.getEmail()返回null时,直接调用eq()方法会触发参数校验空指针,多条件动态查询场景下,不要硬编码所有where条件,需要先判断参数非空再追加对应条件,修改后的代码如下:

// 先构建基础查询
var query = cbf.create(em, WalletReportDto.class)
        .fromSubquery(WalletCTE.class, "offerCTO").from(TenantBalanceOffers.class, "tbo")
        .bind("walletId").select("tbo.wallet.id")
        .bind("amount").select("SUM(tbo.amount)")
        .groupBy("tbo.wallet.id").end()
        .joinOn(TenantWallet.class, "tw", JoinType.INNER)
        .onExpression("offerCTO.walletId = tw.id")
        .end()
        .select("MIN(tw.createdDate)", "fromDate")
        .select("MAX(tw.createdDate)", "toDate")
        .select("tw.customer.email", "email")
        .select("sum(offerCTO.amount)", "totalAmount");

// 动态追加条件:仅参数非空时才加入查询条件
if (criteria.getEmail() != null) {
    query.where("tw.customer.email").eq(criteria.getEmail());
}
// 其他查询条件同理追加即可
if (criteria.getMinTotalAmount() != null) {
    query.where("sum(offerCTO.amount)").ge(criteria.getMinTotalAmount());
}
if (criteria.getFromDate() != null) {
    query.where("tw.createdDate").ge(criteria.getFromDate());
}

// 最终执行查询
List<WalletReportDto> result = query
        .groupBy("tw.id")
        .getResultList();

如果使用Querydsl API,还可以借助BooleanBuilder更方便的组装动态条件:

BooleanBuilder conditionBuilder = new BooleanBuilder();
if (criteria.getEmail() != null) {
    conditionBuilder.and(QTenantWallet.tenantWallet.customer.email.eq(criteria.getEmail()));
}
if (criteria.getFromDate() != null) {
    conditionBuilder.and(QTenantWallet.tenantWallet.createdDate.goe(criteria.getFromDate()));
}
// 直接传入组装好的条件
query.where(conditionBuilder);

另外注意你原代码中select("MIN(tw.createdDate)", "fromtDate")的别名存在笔误,多写了一个t,建议修正为fromDate避免后续DTO映射失败。


内容的提问来源于stack exchange,提问作者java dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 06:57:00