hibernate - 如何使用 JPA + MySQL 在 Spring Boot 中实现全文搜索
问题描述
public class Product {
private Long id;
private String name;
private String description;
}
有没有办法使用 JpaRepository 实现对 Product 类的描述的全文搜索?
解决方案
您可以使用Hibernate Search,这是一个插入 Hibernate ORM 的库,可在您将实体发送到数据库时即时将实体索引到文件系统上的 Lucene 索引中。请参阅入门指南。
(编辑:现在 Hibernate Search 还支持使用 Elasticsearch 作为后端;它会自动在 Elasticsearch 或本地 Lucene 索引中复制您的数据库的一部分,无论您选择哪个。)
查询 Lucene/Elasticsearch 索引与查询数据库有点不同,因此您不能像通常那样使用 HQL 或 Criteria。Hibernate Search 提供了自己的查询 DSL。
如果你想在你的存储库中使用自动生成的方法实现,你可以依赖Snowdrop,它是一个 Hibernate Search / Spring Data 集成,但它已经有一段时间没有更新了。
您最好的选择可能是在您的存储库接口中定义查询方法,然后使用 Hibernate Search APIs 自己实现它们。它真的没有那么复杂,除了最明显的查询之外,它通常被推荐用于所有查询。请参阅Spring Data JPA 文档。
基本上你会得到类似下面的代码片段。请记住,您需要在此工作之前重新索引您的数据库!有关更多信息,请参阅入门指南。
使用休眠搜索 6+:
@Indexed // Add this
public class Product {
private Long id;
@FullTextField // And this
private String name;
@FullTextField // And this
private String description;
}
public interface ProductRepository extends CrudRepository<Product, Long>, CustomizedProductRepository {
// Declare automatically generated methods here
}
public interface CustomizedProductRepository {
List<Product> search(String terms, int limit, int offset);
}
public class CustomizedProductRepositoryImpl implements CustomizedProductRepository {
@PersistenceContext
private EntityManager em;
@Override
public List<Product> search(String terms, int limit, int offset) {
return Search.session(em).search(Product.class)
.where(f -> f.match()
.fields("name", "description")
.matching(terms))
.fetchHits(offset, limit);
}
}
或使用休眠搜索 5:
@Indexed // Add this
public class Product {
private Long id;
@Field // And this
private String name;
@Field // And this
private String description;
}
public interface ProductRepository extends CrudRepository<Product, Long>, CustomizedProductRepository {
// Declare automatically generated methods here
}
public interface CustomizedProductRepository {
List<Product> search(String terms, int limit, int offset);
}
public class CustomizedProductRepositoryImpl implements CustomizedProductRepository {
@PersistenceContext
private EntityManager em;
@Override
public List<Product> search(String terms, int limit, int offset) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity(Product.class).get();
org.apache.lucene.search.Query luceneQuery = queryBuilder
.keyword()
.onFields("name", "description")
.matching(terms)
.createQuery();
// wrap Lucene query in a javax.persistence.Query
javax.persistence.Query jpaQuery =
fullTextEntityManager.createFullTextQuery(luceneQuery, Product.class);
jpaQuery.setMaxResults(limit);
jpaQuery.setFirstResult(offset);
// execute search
return jpaQuery.getResultList();
}
}
推荐阅读
- c# - 如何按顺序调用返回的代表?
- core-data - NSPredicate 检测存在于多个实体关系中的一整组实体
- http - HTTP 日期响应标头何时确定?
- android - rxJava 和应用程序生命周期错误
- python - 梯度值为零的除 GradientDescentOptimizer tensorflow 以外的优化器
- node.js - gps模块停止输出信息
- excel - Excel VBA用户窗体用按钮打开超链接
- php - 重力形式有条件的必填字段
- oracle - 将 TOAD 数据建模器与现有 TOAD Oracle 结合使用
- ruby-on-rails - Rails 4 InvalidCrossOriginRequest 错误