问题
I have list of object which I will read from property file and then I will split with pipe symbol and then I need to apply with or clause. Below is the code. When I try to apply builder.or the below query is getting genareted, instead of or clause.
String coverageNames = env.getRequiredProperty(AmhiConstants.COVERAGE_NAME);
String[] coverageName = coverageNames.split(Pattern.quote("|"));
CriteriaBuilder builder = manager.getCriteriaBuilder();
TypedQuery typedQuery;
CriteriaQuery<Integer> criteriaQuery = builder.createQuery(Integer.class);
Root<BenefitCounter> root = criteriaQuery.from(BenefitCounter.class);
Join<BenefitCounter, BenefitCounterCoverageDetails> benefitCoverageJoin = root
.join(BenefitCounter_.benefitCoverageDetails);
Join<BenefitCounterCoverageDetails, CoverageMaster> coveJoin = benefitCoverageJoin
.join(BenefitCounterCoverageDetails_.coverageType);
List<Predicate> conditions = new ArrayList<>();
conditions.add(builder.and(builder.equal(root.get(BenefitCounter_.isCompleted), 'N')));
for (String coverage : coverageName) {
Predicate predicate = builder.like(builder.lower(coveJoin.get(CoverageMaster_.coverageName)),
AmhiConstants.PERCENTAGE_SYMBOL + coverage + AmhiConstants.PERCENTAGE_SYMBOL);
conditions.add(conditions.add(builder.or(predicate));
}
criteriaQuery.multiselect(root.get(BenefitCounter_.benefitCounterId))
.where(conditions.toArray(new Predicate[] {}));
criteriaQuery.orderBy(builder.asc(root.get(BenefitCounter_.benefitCounterId)));
criteriaQuery.distinct(true);
typedQuery = manager.createQuery(criteriaQuery);
List<Integer> list = typedQuery.getResultList();
return list;
Generated Query:
select distinct benefitcou0_.utilization_dtl_id as col_0_0_ from claims.utilization_dtls benefitcou0_ inner join claims.utilization_coverage_dtls benefitcov1_ on benefitcou0_.utilization_dtl_id=benefitcov1_.utilization_dtl_id inner join claims.coverage_master coveragema2_ on benefitcov1_.coverage_id=coveragema2_.coverage_id where (lower(coveragema2_.coverage_name) like ?) and (lower(coveragema2_.coverage_name) like ?) and (lower(coveragema2_.coverage_name) like ?) and (lower(coveragema2_.coverage_name) like ?) and benefitcou0_.is_completed=? order by benefitcou0_.utilization_dtl_id asc
Acual Query Needed:
select distinct benefitcou0_.utilization_dtl_id as col_0_0_ from claims.utilization_dtls benefitcou0_ inner join claims.utilization_coverage_dtls benefitcov1_ on benefitcou0_.utilization_dtl_id=benefitcov1_.utilization_dtl_id inner join claims.coverage_master coveragema2_ on benefitcov1_.coverage_id=coveragema2_.coverage_id where (lower(coveragema2_.coverage_name) like ?) or (lower(coveragema2_.coverage_name) like ?) or(lower(coveragema2_.coverage_name) like ?) or (lower(coveragema2_.coverage_name) like ?) and benefitcou0_.is_completed=? order by benefitcou0_.utilization_dtl_id asc
回答1:
This is because CriteriaQuery<T>.where(Predicate... restrictions), which is the method you are using, according to JavaDoc,
...Modify the query to restrict the query result according to the conjunction of the specified restriction predicates
Conjunction means a set of "and" predicates. In order to get the "or", you have to use use CriteriaBuilder.or(Predicate... restrictions):
Predicate andPredicate = builder.equal(root.get(BenefitCounter_.isCompleted), 'N');
for (String coverage : coverageName) {
Predicate predicate = builder.like(builder.lower(coveJoin.get(CoverageMaster_.coverageName)),
AmhiConstants.PERCENTAGE_SYMBOL + coverage + AmhiConstants.PERCENTAGE_SYMBOL);
conditions.add(predicate);
}
Predicate orPredicate = builder.or(conditions.toArray(new Predicate[] {}));
Predicate andPredicate = builder.and(andPredicate, orPredicate);
criteriaQuery.multiselect(root.get(BenefitCounter_.benefitCounterId))
.where(andPredicate);
来源:https://stackoverflow.com/questions/57370505/criteria-builder-with-predicate