Spring JPA 规范全文搜索 MYSQL
Spring JPA Specification Full Text Search with MYSQL
我正在尝试使用 Spring JPA 规范创建全文搜索。我要完成的查询如下。
SELECT * FROM Station WHERE MATCH(Slogan, Description) AGAINST('searchText' IN BOOLEAN MODE);
如何在允许我传入 "searchText" 值的 Spring JPA 规范中编写此查询?这是我迄今为止的尝试。
public static Specification<Station> fullTextSearch(String searchText) {
if (searchText == null) {
return null;
}
return (Root<Station> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
List<Predicate> predicates = new ArrayList<>();
Expression<Double> match = cb.function("match", Double.class,
root.get("description"),
cb.parameter(String.class, "searchText"));
// TODO: How do I set "searchText"?????
predicates.add(cb.greaterThan(match, 0.));
return cb.and(predicates.toArray(new Predicate[]{}));
};
}
然后调用即可使用:
Specifications<Station> spec = Specifications.where(StationSpecifications.fullTextSearch(query));
stationRepository.findAll(spec, pageable);
我第一次尝试使用的文章:
http://pavelmakhov.com/2016/09/jpa-custom-function
看起来 Jpa 规范 API 不允许这样做。方法 toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) 有一个查询参数,它不允许注入参数,它不兼容。而且您无权访问 entityManager。
使用原生 MySQL 查询怎么样(请注意 nativeQuery = true ):
@Query(value = "SELECT * FROM accounts WHERE (COALESCE(first_name,'') LIKE %:firstName% AND COALESCE(last_name,'') LIKE %:lastName%)", nativeQuery = true)
public List<Account> searchByFirstnameAndLastname(@Param("firstName")String firstName,@Param("lastName")String lastName);
?
我提出的解决方案并不理想,但基于@dimirsen 的建议。可分页对象已添加到查询中并按预期工作。
@Query(value = "SELECT * FROM Station s WHERE MATCH(s.slogan, s.description) AGAINST(?1 IN BOOLEAN MODE) ORDER BY ?#{#pageable}",
countQuery = "SELECT * FROM Station s WHERE MATCH(s.slogan, s.description) AGAINST(?1 IN BOOLEAN MODE)",
nativeQuery = true)
Page<Station> fullTextSearch(String searchText, Pageable pageable);
我正在尝试使用 Spring JPA 规范创建全文搜索。我要完成的查询如下。
SELECT * FROM Station WHERE MATCH(Slogan, Description) AGAINST('searchText' IN BOOLEAN MODE);
如何在允许我传入 "searchText" 值的 Spring JPA 规范中编写此查询?这是我迄今为止的尝试。
public static Specification<Station> fullTextSearch(String searchText) {
if (searchText == null) {
return null;
}
return (Root<Station> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
List<Predicate> predicates = new ArrayList<>();
Expression<Double> match = cb.function("match", Double.class,
root.get("description"),
cb.parameter(String.class, "searchText"));
// TODO: How do I set "searchText"?????
predicates.add(cb.greaterThan(match, 0.));
return cb.and(predicates.toArray(new Predicate[]{}));
};
}
然后调用即可使用:
Specifications<Station> spec = Specifications.where(StationSpecifications.fullTextSearch(query));
stationRepository.findAll(spec, pageable);
我第一次尝试使用的文章: http://pavelmakhov.com/2016/09/jpa-custom-function
看起来 Jpa 规范 API 不允许这样做。方法 toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) 有一个查询参数,它不允许注入参数,它不兼容。而且您无权访问 entityManager。 使用原生 MySQL 查询怎么样(请注意 nativeQuery = true ):
@Query(value = "SELECT * FROM accounts WHERE (COALESCE(first_name,'') LIKE %:firstName% AND COALESCE(last_name,'') LIKE %:lastName%)", nativeQuery = true)
public List<Account> searchByFirstnameAndLastname(@Param("firstName")String firstName,@Param("lastName")String lastName);
?
我提出的解决方案并不理想,但基于@dimirsen 的建议。可分页对象已添加到查询中并按预期工作。
@Query(value = "SELECT * FROM Station s WHERE MATCH(s.slogan, s.description) AGAINST(?1 IN BOOLEAN MODE) ORDER BY ?#{#pageable}",
countQuery = "SELECT * FROM Station s WHERE MATCH(s.slogan, s.description) AGAINST(?1 IN BOOLEAN MODE)",
nativeQuery = true)
Page<Station> fullTextSearch(String searchText, Pageable pageable);