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
相关产品推荐
相关产品推荐

