How to pass variable number of parameters to Sprin

2019-08-21 08:39发布

问题:

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.

回答1:

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.



回答2:

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