外部实体更改后索引不更新

时间:2014-04-17 14:45:41

标签: java jpa indexing hibernate-mapping hibernate-search

我目前正在开发一个项目,用JPA 2.1保存数据,并使用hibernate search 4.5.0.final搜索实体。

映射类和索引后,搜索工作正常。

但是,当我将classB的值 description 从“someStr”更改为“anotherStr”时。数据库已相应更新,但是当我使用Luke检查索引时,索引中的classA.classB.description未更新,并且数据无法通过关键字“anotherStr”进行搜索,但可以通过关键字“someStr”进行搜索。

在重新索引整个数据库之后,它最终会更新。

根据Hibernate搜索网站,

  

简短的回答是索引是自动的:Hibernate Search将透明地索引通过Hibernate ORM持久化,更新或删除的每个实体。它的任务是保持索引和数据库同步,让你忘记这个问题。

但它不适用于我的情况。我不确定我是否错过了一些细节,或者我需要自己处理这类问题。

我还尝试按照this one的建议在classB上添加@Indexed注释,但它仍然没有解决我的问题。

据我所知,解决方案是定期重新索引数据库。但重新索引会禁用搜索功能,在大多数情况下这不是一个选项。

有人能提出一些建议吗?感谢。

我有一个使用@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();

3 个答案:

答案 0 :(得分:0)

您错误地放置了ContainedIn注释。根据Hibernate Search文档:

  

小心点。因为在使用@InededEmbedded技术时,Lucene索引中的数据是非规范化的,所以Hibernate Search需要知道Place对象的任何更改以及Address对象中的任何更改,以使索引保持最新。为确保Place Lucene文档在地址更改时更新,您需要使用@ContainedIn标记双向关系的另一面。

在您的示例中,您需要:

  1. 使类之间的关系双向
  2. 将ClassB中的关系标记为ContainedIn
  3. 在你的情况下:

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

答案 1 :(得分:0)

我有类似的问题,但已经有正确的注释。就我而言,我已经将强制刷新添加到数据库中,然后对其进行索引和刷新:

myEm.flush();   
Search.getFullTextEntityManager(myEm).flushToIndexes();
myEm.refresh(updatedObject);

答案 2 :(得分:-1)

嗯,添加@ContainedIn并不适合我。

我把示例项目放在这里 https://github.com/yhjhoo/princeSSH

更新部门对象无法更新人员索引