Hibernate Search 在插入后不会重新索引 lucene 索引
Hibernate Search doesn't reindex lucene index after insert
我正在为我的 Spring Web 应用程序使用 Hibernate(带有 JPA)和 Hibernate Search。
当应用程序在服务器上启动时,我使用以下代码创建索引:
EntityManager em = emf.createEntityManager();
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
fullTextEntityManager.createIndexer().startAndWait();
em.close();
这很有魅力。但是,当我通过 Hibernate 插入新实体时,索引不会被修改为包含新实体。根据 Hibernate 文档;这应该会自动发生。
这是我插入实体的方式:
EntityTransaction tx = null;
EntityManager em = emf.createEntityManager();
try {
tx = em.getTransaction();
tx.begin();
em.persist(account);
em.flush();
tx.commit();
}
catch (RuntimeException e) {
if ( tx != null && tx.isActive() ) tx.rollback();
return null;
}
这就是我使用 Hibernate Search 的方式:
EntityManager em = emf.createEntityManager();
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
em.getTransaction().begin();
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity(AccountPojo.class).get();
org.apache.lucene.search.Query luceneQuery = qb
.keyword()
.onFields("id", "user.email", "user.firstName", "user.lastName", "user.phoneNumber", "user.streetAddress")
.matching(term)
.createQuery();
// wrap Lucene query in a javax.persistence.Query
org.hibernate.search.jpa.FullTextQuery jpaQuery =
fullTextEntityManager.createFullTextQuery(luceneQuery, AccountPojo.class);
jpaQuery.setProjection(FullTextQuery.SCORE, FullTextQuery.THIS, "id", "user.email", "user.firstName", "user.lastName", "user.phoneNumber");
// execute search
List result = jpaQuery.getResultList();
em.getTransaction().commit();
em.close();
return result;
当我插入帐户时,在我重新启动应用程序之前无法搜索(索引)它。
正如我所说,配置是使用 JPA 注释进行的。
我在这里遗漏了什么吗?
Hibernate Search 将在提交事务时将更新应用于索引。
在您的示例中,您是 运行 在存储实体之后但在提交之前进行的搜索;您应该在后续交易中测试查询,这是您在实践中大多数情况下需要的。
因为这听起来很奇怪,所以解释似乎是有序的:选择这种设计的一个原因是 Lucene 是非事务性的,所以如果我们在提交之前应用更改,其他线程会看到已经在提交中的更改索引但无法加载实体。
也无法保证交易的正确恢复 rollback/abort/crash.
更新 Lucene 索引可能相对较慢,因此它应用了一些性能技巧。其中,Hibernate Search 在更高效的组合批 IO 操作中合并了并行索引更新。它不仅仅是合并来自同一事务的所有写入,而是合并来自同一应用程序上发生的所有事务的所有写入。
换句话说,如果在提交事务之前应用索引写入,性能会很糟糕。
事实证明,这个答案的解决方案非常简单。
在上面的示例中,我正在保存一个帐户,然后尝试通过 相关实体(用户) 上的一些属性来搜索它。当您将一个对象与包含在您的查询之一中的相关实体持久化时,您需要执行以下操作:
em.refresh(account)
在你坚持之后。否则相关实体的索引将不会重建,因此您将无法通过相关实体的属性找到您的新实体。
我正在为我的 Spring Web 应用程序使用 Hibernate(带有 JPA)和 Hibernate Search。 当应用程序在服务器上启动时,我使用以下代码创建索引:
EntityManager em = emf.createEntityManager();
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
fullTextEntityManager.createIndexer().startAndWait();
em.close();
这很有魅力。但是,当我通过 Hibernate 插入新实体时,索引不会被修改为包含新实体。根据 Hibernate 文档;这应该会自动发生。
这是我插入实体的方式:
EntityTransaction tx = null;
EntityManager em = emf.createEntityManager();
try {
tx = em.getTransaction();
tx.begin();
em.persist(account);
em.flush();
tx.commit();
}
catch (RuntimeException e) {
if ( tx != null && tx.isActive() ) tx.rollback();
return null;
}
这就是我使用 Hibernate Search 的方式:
EntityManager em = emf.createEntityManager();
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
em.getTransaction().begin();
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity(AccountPojo.class).get();
org.apache.lucene.search.Query luceneQuery = qb
.keyword()
.onFields("id", "user.email", "user.firstName", "user.lastName", "user.phoneNumber", "user.streetAddress")
.matching(term)
.createQuery();
// wrap Lucene query in a javax.persistence.Query
org.hibernate.search.jpa.FullTextQuery jpaQuery =
fullTextEntityManager.createFullTextQuery(luceneQuery, AccountPojo.class);
jpaQuery.setProjection(FullTextQuery.SCORE, FullTextQuery.THIS, "id", "user.email", "user.firstName", "user.lastName", "user.phoneNumber");
// execute search
List result = jpaQuery.getResultList();
em.getTransaction().commit();
em.close();
return result;
当我插入帐户时,在我重新启动应用程序之前无法搜索(索引)它。 正如我所说,配置是使用 JPA 注释进行的。
我在这里遗漏了什么吗?
Hibernate Search 将在提交事务时将更新应用于索引。 在您的示例中,您是 运行 在存储实体之后但在提交之前进行的搜索;您应该在后续交易中测试查询,这是您在实践中大多数情况下需要的。
因为这听起来很奇怪,所以解释似乎是有序的:选择这种设计的一个原因是 Lucene 是非事务性的,所以如果我们在提交之前应用更改,其他线程会看到已经在提交中的更改索引但无法加载实体。 也无法保证交易的正确恢复 rollback/abort/crash.
更新 Lucene 索引可能相对较慢,因此它应用了一些性能技巧。其中,Hibernate Search 在更高效的组合批 IO 操作中合并了并行索引更新。它不仅仅是合并来自同一事务的所有写入,而是合并来自同一应用程序上发生的所有事务的所有写入。 换句话说,如果在提交事务之前应用索引写入,性能会很糟糕。
事实证明,这个答案的解决方案非常简单。 在上面的示例中,我正在保存一个帐户,然后尝试通过 相关实体(用户) 上的一些属性来搜索它。当您将一个对象与包含在您的查询之一中的相关实体持久化时,您需要执行以下操作:
em.refresh(account)
在你坚持之后。否则相关实体的索引将不会重建,因此您将无法通过相关实体的属性找到您的新实体。