Reputation: 983
I need to replicate this query into JPA CriteriaBuilder code:
....
where
article.client_id = 1
and article.price > 0
and (
article.code like '%this is statement%'
or article.oem_code like '%this is statement%'
or (
article.description like '%this%'
and article.description like '%is%'
and article.description like '%statement%'
)
)
and here's my code:
...
Root<Article> article = cq.from(Article.class);
List<Predicate> predicates = new ArrayList<Predicate>();
predicates.add(cb.equal(article.get(Article_.clientId), filter.getClientId()));
predicates.add(cb.greaterThan(article.get(Article_.price), BigDecimal.ZERO));
String searchQuery = filter.getSearchQuery();
Predicate disjunction = cb.disjunction();
disjunction.getExpressions().add(cb.like(article.get(Article_.code), "%" + searchQuery + "%"));
disjunction.getExpressions().add(cb.like(article.get(Article_.oem_code), "%" + searchQuery + "%"));
List<Predicate> andPredicate = new ArrayList<Predicate>();
for (String str : searchQuery.split(" ")) {
andPredicate.add(cb.like(article.get(Article_.description), "%" + str + "%"));
}
Now, how can I add this andPredicate
to my disjunction predicate? The getExpressions().add(...)
does not take a Predicate
as param.
Thanks
Upvotes: 6
Views: 26626
Reputation: 362
Note that with the latest JPA 3 Criteria API code like Predicate.getExpressions().add(...)
will not work. It does work in the Hibernate 5 Criteria API (and many people, including me, used it) - but in Hibernate 6, the Hibernate 5 Criteria API is no longer supported and is replaced by the JPA Criteria API - and such code will cease to work.
For example, Spring Boot 3 uses Hibernate 6 and therefore uses JPA 3 for the Criteria API.
Bottom line is code like that quoted above:
disjunction.getExpressions().add(cb.like(article.get(Article_.code), "%" + searchQuery + "%"));
disjunction.getExpressions().add(cb.like(article.get(Article_.oem_code), "%" + searchQuery + "%"));
..will not modify the disjunction Predicate at all.
It should never have modified the Predicate - as defined in the JavaDoc https://javadoc.io/doc/jakarta.persistence/jakarta.persistence-api/latest/jakarta.persistence/jakarta/persistence/criteria/Predicate.html ("Modifications to the list do not affect the query."). The latest implementations of the Predicate interface conform to the JavaDoc.
A good description of combining and/or Predicates is here: https://www.baeldung.com/jpa-and-or-criteria-predicates
That will work no matter what version of the CriteriaAPI you are using.`
Upvotes: 1
Reputation: 983
So here it's what I did and seems that is working fine:
...
Predicate pr1 = cb.like(article.get(Article_.code), "%" + searchQuery + "%");
Predicate pr2 = cb.like(article.get(Article_.oem_code), "%" + searchQuery + "%");
Predicate pr3 = cb.conjunction();
for (String str : busquedaSplit) {
Predicate newPredicate = cb.like(article.get(Article_.description), "%" + str + "%");
pr3 = cb.and(pr3, newPredicate);
}
disjunction = cb.or(pr1, pr2, pr3);
predicates.add(disjunction);
Upvotes: 18