【问题标题】:index not updating after external entity changes外部实体更改后索引未更新
【发布时间】:2014-06-01 21:56:43
【问题描述】:

我目前正在开展一个项目,以使用 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();

【问题讨论】:

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


    【解决方案1】:

    您错误地放置了 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;
        }
    
        ....
    }
    

    【讨论】:

    • 嗨@skapral,感谢您的回答!我不确定您所说的“linkedObjects”是什么意思。应该是 Set 吗?
    • 我的评论有误。更新。对不起。当然应该是ClassA
    • 我做了一些测试代码,确实可以正常工作。但是,在我的案例中,关系映射有点复杂,无法建立双向关系,因此我使用了某种解决方法来手动维护外部更改。无论如何感谢您的回答。
    • @KyneH 您介意分享一下解决方法吗?我遇到了与上述相同的问题,但模型过于复杂,无法在任何地方创建双向关联
    【解决方案2】:

    我遇到了类似的问题,但已经有了正确的注释。就我而言,我已经向数据库和索引添加了强制刷新,并在之后刷新了它:

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

    【讨论】:

      【解决方案3】:

      嗯,添加 @ContainedIn 对我不起作用。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-12
        • 1970-01-01
        • 2020-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多