【问题标题】:Hibernate Search doesn't reindex lucene index after insert插入后休眠搜索不会重新索引 lucene 索引
【发布时间】:2015-04-29 06:33:09
【问题描述】:

我正在为我的 Spring Web 应用程序使用 Hibernate(使用 JPA)和 Hibernate Search。 当应用程序在服务器上启动时,我使用以下代码创建索引:

EntityManager em = emf.createEntityManager();

FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
fullTextEntityManager.createIndexer().startAndWait();

em.close();

这就像一个魅力。但是,当我通过 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 注释进行的。

这里有什么我遗漏的吗?

【问题讨论】:

  • 春天你有什么事务管理器?我依稀记得这是一个微妙的问题(因为重新索引发生在事务提交时)。我觉得应该是JPA事务管理器。
  • 我正在使用 JPA 事务管理器:javax.persistence.EntityTransaction;

标签: java spring hibernate jpa hibernate-search


【解决方案1】:

事实证明,这个答案的解决方案非常简单。 在上面的示例中,我保存了一个帐户,然后尝试通过 相关实体(用户) 上的某些属性对其进行搜索。当您使用包含在其中一个查询中的相关实体持久保存对象时,您需要执行以下操作:

em.refresh(account)

在你坚持之后。否则相关实体的索引将不会被重建,因此您将无法通过相关实体的属性找到您的新实体。

【讨论】:

    【解决方案2】:

    Hibernate Search 将在事务提交时将更新应用于索引。 在您的示例中,您在存储实体之后但在提交之前运行搜索;您应该在后续事务中测试查询,这在大多数情况下是您在实践中需要的。

    因为这听起来很奇怪,所以似乎有一个解释:这种设计选择的一个原因是 Lucene 是非事务性的,所以如果我们要在提交之前应用更改,其他线程会看到索引中已经存在的更改但无法加载实体。 也无法保证在事务回滚/中止/崩溃时正确还原。

    更新 Lucene 索引可能相对较慢,因此它应用了一些性能技巧。其中,Hibernate Search 将并行索引更新合并到更高效的组合批处理 IO 操作中。它不仅仅是合并来自同一事务的所有写入,而是合并来自同一应用程序上发生的所有事务的所有写入。 换句话说,如果在事务提交之前应用索引写入,性能会很糟糕。

    【讨论】:

    • 感谢您的回答。如果我的代码示例有点混乱,我很抱歉;但是这两个块实际上来自两种不同的方法,在不同的时间被调用。 IE,搜索部分实际上比插入要晚得多。因此,不幸的是,您的回答并不能解释这种奇怪之处。谢谢你让我更聪明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多