您好,我想使用QueryDSL创建带有参数的JPA查询,代码如下
private static JPAQuery<Tuple> projectionQuery(JPAQuery<?> query, QCoupon qCoupon, QCouponApplication qCouponApplication) {
return query.select(
qCoupon.id,
qCoupon.code,
qCoupon.status,
qCoupon.amount,
qCoupon.benefitType,
qCoupon.maxDiscountPerApplication,
qCoupon.additionalMonth,
qCouponApplication.count().as("usedQuota"),
qCoupon.globalQuota,
qCoupon.basePriceOnly
);
}
public GetCouponsResponseDTO getCouponsRewrited(String code, ZonedDateTime startCreatedDate, ZonedDateTime endCreatedDate, CouponStatus status, Integer pageNumber, Integer pageSize) {
QCoupon qCoupon = QCoupon.coupon;
QCouponApplication qCouponApplication = QCouponApplication.couponApplication;
PageRequest pageRequest = new PageRequest(pageNumber, pageSize);
JPAQuery<?> query =
projectionQuery(new JPAQuery<>(), qCoupon, qCouponApplication)
.from(qCoupon).leftJoin(qCoupon.applications, qCouponApplication)
.groupBy(qCoupon)
.orderBy(new OrderSpecifier<>(Order.DESC, qCoupon.createdAt));
if (StringUtils.isNotBlank(code)) {
ParamExpression<String> codeParam = new ParamExpressionImpl<>(String.class);
query = query.where(qCoupon.code.likeIgnoreCase(codeParam)).set(codeParam, '%' + code + '%');
}
if (Objects.nonNull(startCreatedDate)) {
ParamExpression<ZonedDateTime> createdAtParam = new ParamExpressionImpl<>(ZonedDateTime.class);
query = query.where(qCoupon.createdAt.goe(createdAtParam)).set(createdAtParam, startCreatedDate);
}
if (Objects.nonNull(endCreatedDate)) {
ParamExpression<ZonedDateTime> endedAtParam = new ParamExpressionImpl<>(ZonedDateTime.class);
query = query.where(qCoupon.createdAt.loe(endedAtParam)).set(endedAtParam, endCreatedDate);
}
......
final String queryString = query.toString();
final TypedQuery<Object[]> typedQuery = entityManager.createQuery(queryString, Object[].class)
.setFirstResult(pageRequest.getOffset())
.setMaxResults(pageRequest.getPageSize());
for (Map.Entry<ParamExpression<?>, Object> paramExpressionObjectEntry : query.getMetadata().getParams().entrySet()) {
ParamExpression<?> paramExpression = paramExpressionObjectEntry.getKey();
typedQuery.setParameter(paramExpression.getName(), paramExpressionObjectEntry.getValue());
}
List<Object[]> queryResult = typedQuery
.getResultList();
问题是queryString
变量包含未命名的参数,例如where lower(coupon.code) like lower(?1)
,与以:
开头的命名参数不符。我尝试使用名称,在ParamExpressionImpl
中添加第二个构造函数参数,就像new ParamExpressionImpl<>(String.class, qCoupon.code.getMetadata().getName())
一样。
因此,它返回并显示异常消息Parameter with that name [code] did not exist
。如何在ParamExpression
行上正确使用QueryDSL的typedQuery.setParameter(...)
?
ParamExpressionImpl
,应使用com.querydsl.core.types.dsl.Param
,它也接受String参数,它将是参数(:parameter
)的名称。