QueryDSL如何将ParamExpression添加到要通过EntityManager.createQuery执行的JPAQuery

问题描述 投票:0回答:1

您好,我想使用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(...)

java querydsl
1个回答
0
投票
代替ParamExpressionImpl,应使用com.querydsl.core.types.dsl.Param,它也接受String参数,它将是参数(:parameter)的名称。
© www.soinside.com 2019 - 2024. All rights reserved.