我正在使用Spring数据进行分页和排序。但是,我想执行多列搜索。
现在,我在我的存储库接口中使用注释@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);
}
我想知道是否有另一种方法可以做到,因为表中的列数可能很高。
谢谢你的帮助。
edit(在Brandon Oakley的评论之后澄清问题):这个解决方案的问题在于@Query注释的where子句,因为我们必须为我们想要搜索的每一列重复完全相同的searchtext参数
结合前面的两个答案:如果您不想将API和数据库模式结合起来,或者换句话说,您不想让用户提供字符串列名,您可以过滤掉那些不是字符串的属性,并将< code>like应用于所有不是字符串的属性。在下面的示例中,它将尝试在列的值中搜索< code > text :< code > name 、< code>field1 、< code>field2和< code>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;
}
规格示例:
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)
);
}
};
}
}
存储库示例:
public interface MyEntityRepository extends PagingAndSortingRepository<MyEntity, Integer> {
List<MyEntity> findAll(Specification<MyEntity> spec);
}
使用示例:
List<MyEntity> res = failureRepository.findAll(Specifications.where(FailureSpecification.textInAllColumns(text)));
另一个更新(在所有类型的列中搜索,并使用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));
}
}
您可以使用规格。这也为您提供了更大的灵活性。您可以有一个方法,但对一个查询使用多个规范:
Page<Item> findAll(Specification<T> spec, Pageable pageable);
myRepository.findAll(textInAllColumns(searchText), pageable);
以下是该用户规范的示例:
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")))
问题内容: 我正在使用Spring Data进行分页和排序。但是,我想执行多列搜索。 现在,我在存储库界面中使用注释 @Query ,如下所示: 编辑: 此解决方案中的问题在于@Query注释的where子句,因为我们必须对要搜索的每一列重复完全相同的searchtext参数 (在Brandon Oakley的评论后澄清问题) 我想知道是否还有另一种方法,因为表中的列数可能很高。 谢谢你的帮助。
我与MongoDB和Spring数据的聚合框架进行了相当长的一段时间的斗争,我实际上想知道我想做的事情是否真的可能。 null 我试图从这种方法开始,但我找不到如何在一个聚合pipeline中完成所有事情的方法:
问题内容: 我正在尝试提供一种搜索功能,该功能将搜索多列以查找基于关键字的匹配项。该查询: 仅适用于搜索一列,我注意到用逗号分隔列名称会导致错误。那么可以在mysql中搜索多个列吗? 问题答案: 您可以使用AND或OR运算符,具体取决于要返回的搜索内容。 这两个子句必须匹配才能返回记录。或者: 如果任一子句匹配,则将返回记录。 有关使用MySQL SELECT查询可以执行的操作的更多信息,请尝试使
问题背景 之前做springboot项目在操作数据库方面一直在使用的是Mybatis,最近在查阅资料的时候接触到了SpringData JPA与SpringData JDBC,想问一下大佬们,这三个框架如何选型
我想在Spring-Boot后端创建一个多字段搜索。如何使用实现这一点? 环境 前端的UI是Jquery DataTable。每列允许应用单个字符串搜索项。跨多个列的搜索词由联接。 看来QueryDSL是解决这个问题的更简单、更好的方法。我在用Gradle。我需要改变我的构造吗?
我是Neo4j和SDN的新手。我试图使用@index(unique=true)为我的实体创建主键。它创建唯一的节点,但如果使用索引的相同属性值,它将替换其他属性。如: 但是,我想抛出一个关于主键冲突/重复节点的异常。 有什么方法可以达到同样的效果吗?