I need to pass in a variable number of parameters to a spring/JPA repo to mimick something like this.
select * from myTable
where name like '%SOME_VALUE%'
or name like '%SOME_OTHER_VALUE%'
or name like '%SOME_OTHER_VALUE2%'
or an unknown number of other values
So far I haven't been able to determine what the correct way to to do this is. I'm using Spring 4.3.7, Hibernate 5.2.9, and Spring Data 1.11.1. I've googled around and it doesn't appear that there's way to do this with a normal CRUD repo, but so far I haven't found any examples that look like what I need. I think CriteriaBuilder
is what I am supposed to use, but that seems to have fallen out of favor, so I'm not sure what the correct way to do this is.
Perhaps you are looking for something like this?:
@Query("select e from Entity e "
+"where (:field1 = '' or e.field1 like '%:field1%') "
+"and (:field2 = '' or e.field2 like '%:field2%') "
//...
+"and (:fieldN = '' or e.fieldN like '%:fieldN%')"
Page<Entity> advancedSearch(@Param("field1") String field1,
@Param("field2") String field2,
//...
@Param("fieldN") String fieldN,
Pageable page);
Source.
So I followed @Jorge Campos advice and used specification. My code looks like this now:
public Stream<Product> findProductsContainingDesc(Collection<String> withDesc) {
Specifications<Product> specifications = null;
for (String s : withDesc) {
if(specifications == null){
specifications = where(hasDescriptionLike(s));
}else{
specifications = specifications.or(hasDescriptionLike(s));
}
}
return internalProductRepository.findAll(specifications).stream();
}
public static Specification<Product> hasDescriptionLike(String desc) {
return (root, query, builder) -> builder.like(root.get("description"), "%" + desc + "%");
}
And my repo definition is this.
interface InternalProductRepository extends JpaRepository<Product, Long>, JpaSpecificationExecutor