Spring Data - Multi-column searches

前端 未结 5 1976
心在旅途
心在旅途 2020-12-01 10:05

I am using Spring Data for the paging and the sorting. However, I would like to perform multi-columns searches.

Now, I am using the annotation @Query in my r

5条回答
  •  感情败类
    2020-12-01 10:33

    Combining previous two answers: if you don't want to couple your API and your database schema or in other words you don't want the user to provide a string column name - you can filter out those attributes that are not strings and apply like to all those that are. In the following example it will try to search text in values of columns: name,field1, field2 and field3.

    Entity Example:

    @Entity
    public class MyEntity {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        public int id;
        public String name;
        public String field2;
        public String field3;
        public String field4;
    }
    

    Specification Example:

    public class EntitySpecification {
    
        public static Specification textInAllColumns(String text) {
    
            if (!text.contains("%")) {
                text = "%"+text+"%";
            }
            final String finalText = text;
    
            return new Specification() {
                @Override
                public Predicate toPredicate(Root root, CriteriaQuery cq, CriteriaBuilder builder) {
                    return builder.or(root.getModel().getDeclaredSingularAttributes().stream().filter(a-> {
                        if (a.getJavaType().getSimpleName().equalsIgnoreCase("string")) {
                            return true;
                        }
                        else {
                            return false;
                    }}).map(a -> builder.like(root.get(a.getName()), finalText)
                        ).toArray(Predicate[]::new)
                    );
                }
            };
        }
    
     }
    

    Repository Example:

    public interface MyEntityRepository extends PagingAndSortingRepository {
        List findAll(Specification spec);
    }
    

    Usage example:

    List res = failureRepository.findAll(Specifications.where(FailureSpecification.textInAllColumns(text)));
    

    another update (search in all types of columns with white-listing of fields with lambdas - code is not checked)

    public class EmployeeSpecification {
        public static Specification textInAllColumns(String text, Set fields) {
            if (!text.contains("%")) {
                text = "%" + text + "%";
            }
            final String finalText = text;
    
            return  (Specification) (root, query, builder) -> 
                    builder.or(root.getModel().getDeclaredSingularAttributes().stream().filter(a -> {
                    return fields.contains(a.getName());
                }).map(a -> builder.like(root.get(a.getName()), finalText)).toArray(Predicate[]::new));
        }
    } 
    

提交回复
热议问题