提问者:小点点

在数据库上更新视图时,Hibernate搜索不更新视图的索引


在我的项目中,我们使用Lucene和Hibernate Search/ORM 5.9.2。如果数据库中的一个表被更新,同样的变化会反映在es索引中,那么它会很好地工作。但是数据库视图的索引没有更新。值存在于数据库中,但不存在于索引中。

通过Hibernate搜索实现这个我需要什么相应的策略/逻辑?

任何引用我的实现的代码都可以在Java文件下的implemented code中找到。

此外,让我们假设我有两个A类

当通过Hibernate实体在数据库下更新表时,Hibernate搜索在索引下更新相同的表。但是视图在SQL服务器端更新时不会发生这种行为。这可以通过Lucene/Hibernate搜索实现吗?


共1个答案

匿名用户

Hibernate Search在实体级别运行。因此,它不会看到您直接在数据库中所做的更改。

对于Hibernate Search来管理索引,您需要依赖实体。

对于它来说,真的没有不同的选择,因为这是它的设计目的。

如果对实体进行了更改,则可以实现自己的侦听器层来处理C,或者使C成为一个实体,并在数据库能够做到这一点的情况下,实现一个触发器来丢弃更新查询。

如果更改是直接对数据库进行的,那么您使用Hibernate Search就不走运了。或者每次对数据库进行更改以触发索引时,您都必须触发应用程序中的某些服务。

顺便问一下,您是否需要在数据库级别使用此视图?因为如果您只需要在Elasticsearch级别使用它,您可以将C作为一个适当的实体,将<code>@OneToOne</code>映射到a和B,并在另一侧使用<code>@IndexedEmbedded</code<和<code>@containdIn</code〕对a和B的内容进行索引。这将解决本地Hibernate搜索的问题。

我想我会尝试这样的事情:

 @Entity
 @Indexed
 public class C {
     @Id
     @GeneratedValue
     private Long id;

     @OneToOne(mappedBy = "a")
     // you might need a prefix if some fields are common between a and b
     @IndexedEmbedded
     private A a;

     @OneToOne(mappedBy = "b")
     // you might need a prefix if some fields are common between a and b
     @IndexedEmbedded
     private B b;
 }

然后在 A 中(与 B 相同):

@Entity
@Indexed
public class A {
    // the existing content of your A class

    @OneToOne(cascade = CascadeType.ALL)
    @ContainedIn
    private C c;

    public setC(C c) {
        if ( c != null ) {
            c.setA( this );
        }
        this.c = c;
    }
}

那么在第一次创建A和B的时候,还需要创建一个C,并将其注入A和B中:

C c = new C();
a.setC( c );
b.setC( c );

em.persist( a );
em.persist( c );

完成后,每当您更新A或B时,都应该通过@ContainedIn注释重新索引C。