jpl*_*ain 7 java spring spring-data spring-data-jpa
我正在使用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);
}
Run Code Online (Sandbox Code Playgroud)
编辑:此解决方案中的问题在于@Query注释的where子句,因为我们必须为我们要搜索的每一列重复完全相同的searchtext参数(在Brandon Oakley的评论之后澄清问题)
我想知道是否还有其他方法可以做,因为表中的列数可能很高.
谢谢你的帮助.
以下是此类用户规范的示例:
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)
);
}
Run Code Online (Sandbox Code Playgroud)
甚至更可定制的实施:
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"));
}
Run Code Online (Sandbox Code Playgroud)
用法:
userRepository.findAll(Specifications.where(UserSpecifications.containsTextInName("irs")))
Run Code Online (Sandbox Code Playgroud)
结合前面的两个答案:如果你不想你的夫妇API和数据库架构或者换句话说,你不希望用户提供一个字符串列名-你可以过滤掉那些不是字符串属性和适用like于所有那些。在下面的例子中,它会尝试搜索text列的值:name,field1,field2和field3。
实体示例:
@Entity
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int id;
public String name;
public String field2;
public String field3;
public String field4;
}
Run Code Online (Sandbox Code Playgroud)
规格示例:
public class EntitySpecification {
public static Specification<MyEntity> textInAllColumns(String text) {
if (!text.contains("%")) {
text = "%"+text+"%";
}
final String finalText = text;
return new Specification<MyEntity>() {
@Override
public Predicate toPredicate(Root<MyEntity> 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)
);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
存储库示例:
public interface MyEntityRepository extends PagingAndSortingRepository<MyEntity, Integer> {
List<MyEntity> findAll(Specification<MyEntity> spec);
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
List<MyEntity> res = failureRepository.findAll(Specifications.where(FailureSpecification.textInAllColumns(text)));
Run Code Online (Sandbox Code Playgroud)
另一个更新(在所有类型的列中搜索带有 lambdas 的字段白名单 - 不检查代码)
public class EmployeeSpecification {
public static Specification<Employee> textInAllColumns(String text, Set<String> fields) {
if (!text.contains("%")) {
text = "%" + text + "%";
}
final String finalText = text;
return (Specification<Employee>) (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));
}
}
Run Code Online (Sandbox Code Playgroud)
你可以使用规格.这也为您提供了更大的灵活性.您可以使用一种方法,但对查询使用多个规范:
Page<Item> findAll(Specification<T> spec, Pageable pageable);
myRepository.findAll(textInAllColumns(searchText), pageable);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16719 次 |
| 最近记录: |