Java Spring数据-仅按一个值进行多列搜索

Java Spring数据-仅按一个值进行多列搜索,java,spring,spring-data-jpa,spring-data,Java,Spring,Spring Data Jpa,Spring Data,我使用Spring数据将客户列表添加到我的网格中 在我的存储库中,我有以下方法: public List<CustomerDto> findAllByFirstNameContainingOrLastNameContainingAllIgnoreCase(String firstName, String lastName); 而不是: repository.findAllByFirstNameContainingOrLastNameContainingAllIgnoreCase(f

我使用Spring数据将客户列表添加到我的网格中

在我的存储库中,我有以下方法:

public List<CustomerDto> findAllByFirstNameContainingOrLastNameContainingAllIgnoreCase(String firstName, String lastName);
而不是:

repository.findAllByFirstNameContainingOrLastNameContainingAllIgnoreCase(filterValue, filterValue);

如果您有任何想法或建议,谢谢您的帮助

我能想到的一个通用解决方案是使用JPA规范。这可能是一个过分的解决方案,但如果您有很多用于多列搜索的用例,那么我认为这是值得的

我将首先演示如何使用它

    List<String> bookColumns = Arrays.asList("title", "genre", "author.name");

    // Search "Spring": matches 2 Books - Spring in Action and Spring Integration
    GenericSearchSpecification<Book> searchSpecification =  new GenericSearchSpecification<>(bookColumns, "Spring");
    List<Book> books = bookRepository.findAll(searchSpecification);
    Assert.assertEquals(2, books.size());
List bookColumns=Arrays.asList(“title”、“genre”、“author.name”);
//搜索“Spring”:匹配2本书-Spring在运行和Spring集成
GenericSearchSpecification searchSpecification=新的GenericSearchSpecification(bookColumns,“Spring”);
listbooks=bookRepository.findAll(searchSpecification);
Assert.assertEquals(2,books.size());
GenericSearchSpecification是我创建的一个类,它有一个接受2个参数的构造函数

  • 可搜索列
  • 搜索字符串
现在来看看类的实现

public class GenericSearchSpecification<T> implements Specification<T> {

    private List<String> columns;
    private String search;

    public GenericSearchSpecification(List<String> columns, String search) {
        this.columns = columns;
        this.search = search;
    }

    @Override
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
        List<Predicate> predicates = new ArrayList<>();
        for (String column: columns) {
            Path path = buildPath(column, root);
            Predicate predicate = criteriaBuilder.like(criteriaBuilder.upper(path), "%" + search.toUpperCase() + "%");
            predicates.add(predicate);
        }

        return criteriaBuilder.or(predicates.stream().toArray(Predicate[]::new));
    }

    private Path buildPath(String column, Path path) {

        if (!column.contains(".")) return path.get(column);

        String[] parts = column.split("\\.");
        for (String part: parts) {
            path = path.get(part);
        }

        return path;
    }

}
公共类GenericSearchSpecification实现了该规范{
私有列表列;
私有字符串搜索;
公共GenericSearchSpecification(列表列、字符串搜索){
this.columns=列;
this.search=搜索;
}
@凌驾
公共谓词toPredicate(根根、CriteriaQuery CriteriaQuery、CriteriaBuilder CriteriaBuilder){
列表谓词=新的ArrayList();
for(字符串列:列){
路径路径=构建路径(列,根);
谓词谓词=criteriaBuilder.like(criteriaBuilder.upper(path),“%”加上search.toUpperCase()+“%”;
add(谓词);
}
返回criteriaBuilder.or(predicates.stream().toArray(Predicate[]::new));
}
专用路径buildPath(字符串列,路径){
如果(!column.contains(“.”)返回path.get(column);
String[]parts=column.split(“\\”);
用于(字符串部分:部分){
path=path.get(部分);
}
返回路径;
}
}

如果您有兴趣,请随时访问我专门为此创建的文章:

有趣的解决方案!在规范之间添加intertermediate类可能会增加overkill移动的可行性,以便在搜索的参数中添加相同的字段。我会读你的文章,试着看看!谢谢你回来!你真好!
public class GenericSearchSpecification<T> implements Specification<T> {

    private List<String> columns;
    private String search;

    public GenericSearchSpecification(List<String> columns, String search) {
        this.columns = columns;
        this.search = search;
    }

    @Override
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
        List<Predicate> predicates = new ArrayList<>();
        for (String column: columns) {
            Path path = buildPath(column, root);
            Predicate predicate = criteriaBuilder.like(criteriaBuilder.upper(path), "%" + search.toUpperCase() + "%");
            predicates.add(predicate);
        }

        return criteriaBuilder.or(predicates.stream().toArray(Predicate[]::new));
    }

    private Path buildPath(String column, Path path) {

        if (!column.contains(".")) return path.get(column);

        String[] parts = column.split("\\.");
        for (String part: parts) {
            path = path.get(part);
        }

        return path;
    }

}