弹簧数据 - 多列搜索

2022-09-03 09:58:10

我正在使用Spring Data进行分页和排序。但是,我想执行多列搜索。

现在,我在我的存储库界面中使用注释@Query,如下所示:

public interface MyRepository extends PagingAndSortingRepository<Item,Long> {

    @Query(value="select mt from MY_TABLE mt where mt.field1 = %searchtext% or mt.field2 = %searchtext% or mt.field3 = %searchtext%")    
    Page<Item> findByAllColumns(@Param("searchtext") String searchtext, Pageable pageable);

}

我想知道是否有另一种方法可以做到,因为表中的列数可能很高。

感谢您的帮助。

编辑(在Brandon Oakley的评论之后澄清问题):此解决方案中的问题在于@Query注释的where子句,因为我们必须为要搜索的每一列重复完全相同的searchtext参数


答案 1

以下是此类用户规范的示例:

public static Specification<User> containsTextInName(String text) {
    if (!text.contains("%")) {
        text = "%" + text + "%";
    }
    String finalText = text;
    return (root, query, builder) -> builder.or(
            builder.like(root.get("lastname"), finalText),
            builder.like(root.get("firstname"), finalText)
    );
}

甚至更可定制的实现:

public static Specification<User> containsTextInAttributes(String text, List<String> attributes) {
    if (!text.contains("%")) {
        text = "%" + text + "%";
    }
    String finalText = text;
    return (root, query, builder) -> builder.or(root.getModel().getDeclaredSingularAttributes().stream()
            .filter(a -> attributes.contains(a.getName()))
            .map(a -> builder.like(root.get(a.getName()), finalText))
            .toArray(Predicate[]::new)
    );
}

public static Specification<User> containsTextInName(String text) {
    return containsTextInAttributes(text, Arrays.asList("lastname", "firstname"));
}

用法:

userRepository.findAll(Specifications.where(UserSpecifications.containsTextInName("irs")))

答案 2

您可以使用规范。这也为您提供了更大的灵活性。您可以有一种方法,但对一个查询使用多个规范:

Page<Item> findAll(Specification<T> spec, Pageable pageable);

myRepository.findAll(textInAllColumns(searchText), pageable);

推荐