2015-04-29 4 views
0

Я использую Hibernate (с JPA) и Hibernate Поиск для моего веб-приложения Spring. При запуске приложения на сервере, я создать индексы с помощью следующего кода:Hibernate Search не индексирует индекс lucene после вставки

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.

Есть ли что-то, что мне не хватает здесь?

+0

Какой у вас менеджер по работе с весной? Я смутно помню, что это деликатная проблема (потому что reindex происходит при совершении транзакции). Я думаю, что это должен быть менеджер транзакций JPA. –

+0

Я использую менеджер транзакций JPA: javax.persistence.EntityTransaction; – MichaelCleverly

ответ

1

Как оказалось, решение этого ответа было довольно простым. В приведенном выше примере я сохранил учетную запись и попытался выполнить ее поиск по некоторым свойствам связанного объекта (Пользователь). Когда вы сохранить объект со связанными лицами, которые включены в одном из ваших запросов, что вам нужно сделать:

em.refresh(account) 

после его сохраняется. В противном случае индексы связанных объектов не будут восстановлены, и, следовательно, вы не сможете найти свой новый объект по свойствам реальных объектов.

0

Hibernate Search будет применять обновления к индексу при совершении транзакции. В вашем примере вы запускаете поиск сразу после сохранения объекта, но перед его выполнением; вы должны проверить запрос в последующей транзакции, что вам в большинстве случаев понадобится на практике.

Поскольку это может показаться странным, объяснение представляется по порядку: одна из причин этого выбора заключается в том, что Lucene не является транзакционным, поэтому, если бы мы применили изменения до фиксации, другие потоки увидели бы изменения, уже внесенные в индекс, но не может загрузить объекты. Также было бы невозможно гарантировать правильное возвращение при откате транзакции/прервать/сбой.

Обновление индекса Lucene может быть относительно медленным, поэтому оно применимо к некоторым трюкам производительности. Среди прочего, Hibernate Search объединяет параллельные обновления индексов в более эффективные комбинированные операции ввода-вывода. Это не просто слияние всех записей из одной транзакции, а объединение всех записей из всех транзакций, происходящих в одном приложении. Иными словами, производительность была бы ужасной, если бы она применяла индексные записи до совершения транзакции.

+0

Благодарим вас за ответ. Прошу прощения, если мой пример кода немного запутан; но эти два блока на самом деле состоят из двух разных методов, вызываемых в разное время. IE, часть поиска фактически используется намного позже вставки. Поэтому ваш ответ, к сожалению, не объясняет эту странность. Спасибо, что сделал меня умнее. – MichaelCleverly

Смежные вопросы