简体   繁体   中英

QueryDSL how to add ParamExpression to JPAQuery to be executed with EntityManager.createQuery


Hi, I'd like to create JPA query with parameters using QueryDSL, the code is like

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

The problem is the queryString variable contains unnamed parameter like where lower(coupon.code) like lower(?1) not as expected with named parameter that starts with : . I've tried using name, adding second constructor argument in ParamExpressionImpl like new ParamExpressionImpl<>(String.class, qCoupon.code.getMetadata().getName()) it's just same.

As a result it returns with exception message Parameter with that name [code] did not exist . How's the correct use of QueryDSL's ParamExpression on the typedQuery.setParameter(...) line?

Instead of ParamExpressionImpl you should use com.querydsl.core.types.dsl.Param , which also takes a String argument which will be the name of the parameter ( :parameter ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM