индекс не обновляется после изменения внешнего объекта

В настоящее время я работаю над проектом по сохранению данных с помощью JPA 2.1 и поиску объектов с использованием спящего режима поиска 4.5.0.final.

После сопоставления классов и индексации поиск работает нормально.

Однако, когда я изменил значение описание classB с «someStr» на «anotherStr». База данных была обновлена ​​соответствующим образом, но когда я проверил индекс с помощью Luke, classA.classB.description в индексе не был обновлен, и данные не могут быть доступны для поиска по ключевому слову «anotherStr», но могут быть доступны для поиска по ключевому слову «someStr».

После того, как я переиндексировал всю базу данных, она наконец обновилась.

Согласно поисковому веб-сайту Hibernate,

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

Но это не работает в моем случае. Я не уверен, пропустил ли я какие-то детали или мне нужно справиться с такими проблемами самостоятельно.

Я также попытался добавить аннотацию @Indexed к классу B, как это было предложено этим, но это все еще не решает мою проблему.

Насколько я знаю, решением будет периодическая переиндексация базы данных. Но переиндексация отключит функцию поиска, а это в большинстве случаев невозможно.

Может ли кто-нибудь дать несколько предложений? Спасибо.

У меня есть класс, в который встроены некоторые другие классы с помощью аннотации @IndexedEmbedded. Вот упрощенная версия моего сопоставления классов.

Class A
@Entity(name = "classA")
@Indexed
public class classA extends Model {
    private int id;
    private String name;
    private ClassB place;
    ...
    some constructors
    ...
    @Id
    @GeneratedValue
    @DocumentId
    public int getId() {
        return id;
    }

    @Column(name = "name")
    @Field(analyze = Analyze.NO, store = Store.YES)    // only used for sorting
    public String getName() {
        return name;
    }

    @IndexedEmbedded
    @ManyToOne
    @JoinColumn(name = "place_id")
    public ClassB getPlace() {
        return place;
    }
    ...
}


Class B
@Entity(name = "classB")
public class classB extends Model {
    private int id;
    private String description;
    ...
    some constructors
    ...
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

    @Fields({
        @Field,
        @Field(name = "description_sort", analyze = Analyze.NO, store = Store.YES)
    })
    @ContainedIn
    @Column(name = "description")
    public String getDescription() {
        return description;
    }
    ...
}

И методы индексации следующие:

fullTextEntityManager.createIndexer()
    .purgeAllOnStart(true)
    .optimizeAfterPurge(true)
    .optimizeOnFinish(true)
    .batchSizeToLoadObjects(25)
    .threadsToLoadObjects(8)
    .startAndWait();

person Kyne H    schedule 17.04.2014    source источник


Ответы (3)


Вы неправильно разместили аннотацию ContainedIn. Согласно документации Hibernate Search:

Будь осторожен. Поскольку при использовании метода @IndexedEmbedded данные в индексе Lucene денормализованы, Hibernate Search должен знать о любых изменениях в объекте Place и любых изменениях в объекте Address, чтобы поддерживать индекс в актуальном состоянии. Чтобы убедиться, что документ Place Lucene обновляется при изменении его адреса, необходимо пометить другую сторону двунаправленной связи с помощью @ContainedIn.

В вашем примере вам нужно:

  1. Сделайте отношения между классами двунаправленными
  2. Отметьте отношение в ClassB как ContainedIn

В твоем случае:

ClassB {

    private Set<ClassA> linkedObjects;

    .... 

    @OneToMany(mappedBy="place")
    @ContainedIn
    public Set<ClassA> getLinkedObjects() {
        return linkedObjects;
    }

    ....
}
person skapral    schedule 18.04.2014
comment
Привет @skapral, спасибо за ответ! Я не уверен, что вы подразумеваете под связанными объектами. Должен ли он быть Set‹ClassA›? - person Kyne H; 18.04.2014
comment
В моем комментарии была опечатка. Обновлено. Извиняюсь. Конечно, это должен быть класс А. - person skapral; 18.04.2014
comment
Я сделал несколько тестовых кодов, и они действительно работают так, как ожидалось. Однако сопоставление отношений в моих случаях немного сложно и не может создавать двунаправленные отношения, поэтому я использовал какой-то обходной путь, чтобы вручную поддерживать внешние изменения. В любом случае спасибо за ваш ответ. - person Kyne H; 22.04.2014
comment
@KyneH, не могли бы вы поделиться, каким было обходное решение? У меня та же проблема, что и описанная выше, но у меня слишком сложная модель, чтобы везде можно было создавать двунаправленные ассоциации. - person Jewels; 28.03.2016

У меня была похожая проблема, но уже с правильными аннотациями. В моем случае я добавил принудительную очистку как в базу данных, так и в индекс, а затем обновил ее:

myEm.flush();   
Search.getFullTextEntityManager(myEm).flushToIndexes();
myEm.refresh(updatedObject);
person user715022    schedule 28.12.2017

хммм, добавление @ContainedIn у меня не работает.

Я разместил образец проекта здесь https://github.com/yhjhoo/princeSSH.

Обновить объект отдела не может обновить индекс человека

person 王子1986    schedule 30.06.2016