提问者:小点点

如何在Spring JPA中使用标准生成器实现子查询


我正在尝试使用标准生成器动态实现此本机查询

@Query(nativeQuery = true, value =
        """
                SELECT * FROM unit_register
                WHERE unit_nr IN (
                SELECT DISTINCT(unit_nr)
                FROM local_area_register
                WHERE (service_code = :service_code or :service_code is null)
                AND (country_code = :country_code or :country_code is null)
                AND (postal_code = :postal_code or :postal_code is null)
                AND return_code IN ('F', 'U')
                AND start_date <= CURRENT_DATE
                AND COALESCE(end_date, CURRENT_DATE) >= CURRENT_DATE )
                                    """)
List<UnitRegister> getUnitCodeDetails(@Param("service_code") String serviceCode,
                                      @Param("country_code") String countryCode,
                                      @Param("postal_code") String postalCode);

这是我的实现

public List<UnitRegister> findUnitRegister(String serviceCode, String countryCode, String postalCode) {
    return unitRegisterRepository.findAll((Specification<UnitRegister>) (Root<UnitRegister> root,
                                                                         CriteriaQuery<?> criteriaQuery,
                                                                         CriteriaBuilder criteriaBuilder) -> {

        Subquery<LocalAreaRegister> subQuery = criteriaQuery.subquery(LocalAreaRegister.class);
        Root<LocalAreaRegister> subRoot = criteriaQuery.from(LocalAreaRegister.class);

        List<Predicate> predicates = new ArrayList<>();
        List<Predicate> subPredicates = new ArrayList<>();
        var p = criteriaBuilder.conjunction();

        if (isNotBlank(serviceCode)) {
            subPredicates.add(criteriaBuilder.equal(subRoot.get("id").get("serviceCode"), serviceCode));
        }
        if (isNotBlank(countryCode)) {
            subPredicates.add(criteriaBuilder.equal(subRoot.get("id").get("countryCode"), countryCode));
        }
        if (isNotBlank(postalCode)) {
            subPredicates.add(criteriaBuilder.equal(subRoot.get("id").get("postalCode"), postalCode));
        }

        CriteriaBuilder.Coalesce<LocalDate> coalesce = criteriaBuilder.coalesce();
        coalesce.value(subRoot.get("endDate"));
        coalesce.value(LocalDate.now());

        subPredicates.add(criteriaBuilder.in(subRoot.get("id").get("returnCode")).value(RETURN_CODES_F_U));
        subPredicates.add(criteriaBuilder.lessThanOrEqualTo(subRoot.get("startDate"), LocalDate.now()));
        subPredicates.add(criteriaBuilder.greaterThanOrEqualTo(coalesce, LocalDate.now()));

        System.out.println("******" + subPredicates.size());
        subQuery.select(subRoot.get("id").get("unitNR")).distinct(true).where(subPredicates.toArray(new Predicate[]{}));

        
        return criteriaBuilder.in(root.get("unitNr")).value(subQuery);
    });
}

但它失败并显示以下错误消息:

非预期令牌:在第1行附近,第230列[从no.posten.ph. unit.domain.Unit中选择GeneratedAlias0注册为GeneratedAlias0,no.posten.ph.Unit.domain.LocalArea注册为GeneratedAlias1 where atedAlias0.unitNr in(从何处选择不同的generatedAlias1.id.unitNR(generatedAlias1.id.serviceCode=:Param0)和(generatedAlias1.id.国家代码=:Param1)和(generatedAlias1.id.postalCode=:Param2)和(generatedAlias1.id.returCode in(:Param3))和(GeneratedAlias1.start Date

应用程序//org. hibernate.内部.AbstractSharedSession合同.createQuery(AbstractSharedSessionContract.java:748)…127更多

为了简单地理解错误:

[select generatedAlias0 from no.posten.ph.unit.domain.UnitRegister as generatedAlias0, no.posten.ph.unit.domain.LocalAreaRegister as generatedAlias1 where generatedAlias0.unitNr in (select distinct generatedAlias1.id.unitNR from  **where** ( generatedAlias1.id.serviceCode=:param0 ) and ( generatedAlias1.id.countryCode=:param1 ) and ( generatedAlias1.id.postalCode=:param2 ) and ( generatedAlias1.id.returnCode in (:param3) ) and ( generatedAlias1.startDate<=:param4 ) and ( coalesce(generatedAlias1.endDate, :param5)>=:param6 ))]

这是正在生成的查询,在“where”之前没有表/实体名称,并且在where子句中只添加了1个谓词,尽管有6个谓词


共1个答案

匿名用户

您的代码将根添加到外部查询

Root<LocalAreaRegister> subRoot = criteriaQuery.from(LocalAreaRegister.class);

当您想将其添加到subQuery时,即

Root<LocalAreaRegister> subRoot = subQuery.from(LocalAreaRegister.class);