当在数据库上更新视图时,Hibernate 搜索不更新视图的索引
Hibernate search not updating the index for a view, when view is updated on database
在我的项目中,我们使用 Lucene 和 Hibernate Search/ORM 5.9.2。如果 table 在数据库上更新,它工作得很好,相同的更改反映在 ES 索引上。但是数据库视图的索引没有更新。值存在于数据库下,但不存在于索引下。
通过Hibernate搜索实现这个需要什么对应的strategy/logic?
任何引用我的实现的代码都可以在 下找到。
此外,假设我有 2 类 A 和 B,C 是 A+B 的视图。我将 C 存储在我的弹性索引中。在数据库下更新 A 和 B 后,C 是否有可能更新?因为我正在使用 Hibernate search+lucene 注释。
当通过 Hibernate 实体在数据库下更新 table 时,Hibernate 搜索在索引下更新相同内容。但是这种行为不会发生在视图上,因为它们是在 SQL 服务器端更新的。这可以通过 Lucene/Hibernate 搜索来实现吗?
Hibernate Search 在实体级别运行。所以它看不到您直接在数据库中所做的更改。
要让 Hibernate Search 管理您的索引,您需要依赖实体。
它确实没有选择以不同的方式做事,因为这是它的设计目的。
如果对实体进行了更改,您可以实现自己的侦听器层来处理 C 或使 C 成为实体并实现一个触发器,如果您的数据库可以执行,则删除对其的更新查询。
如果更改是直接对数据库进行的,那么您就不能使用 Hibernate Search。或者你必须在你的应用程序中触发一些服务,每次你对数据库进行更改以触发索引。
顺便说一句,你需要这个数据库级别的视图吗?因为如果您只在 Elasticsearch 级别需要它,您可以使 C 成为具有 A 和 B 的 @OneToOne
的适当实体,并使用 @IndexedEmbedded
和 @ContainedIn
索引 A 和 B 的内容另一边。这将解决您使用本机 Hibernate Search 的问题。
我想我会尝试这样的事情:
@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 应该重新索引。
在我的项目中,我们使用 Lucene 和 Hibernate Search/ORM 5.9.2。如果 table 在数据库上更新,它工作得很好,相同的更改反映在 ES 索引上。但是数据库视图的索引没有更新。值存在于数据库下,但不存在于索引下。
通过Hibernate搜索实现这个需要什么对应的strategy/logic?
任何引用我的实现的代码都可以在
此外,假设我有 2 类 A 和 B,C 是 A+B 的视图。我将 C 存储在我的弹性索引中。在数据库下更新 A 和 B 后,C 是否有可能更新?因为我正在使用 Hibernate search+lucene 注释。
当通过 Hibernate 实体在数据库下更新 table 时,Hibernate 搜索在索引下更新相同内容。但是这种行为不会发生在视图上,因为它们是在 SQL 服务器端更新的。这可以通过 Lucene/Hibernate 搜索来实现吗?
Hibernate Search 在实体级别运行。所以它看不到您直接在数据库中所做的更改。
要让 Hibernate Search 管理您的索引,您需要依赖实体。
它确实没有选择以不同的方式做事,因为这是它的设计目的。
如果对实体进行了更改,您可以实现自己的侦听器层来处理 C 或使 C 成为实体并实现一个触发器,如果您的数据库可以执行,则删除对其的更新查询。
如果更改是直接对数据库进行的,那么您就不能使用 Hibernate Search。或者你必须在你的应用程序中触发一些服务,每次你对数据库进行更改以触发索引。
顺便说一句,你需要这个数据库级别的视图吗?因为如果您只在 Elasticsearch 级别需要它,您可以使 C 成为具有 A 和 B 的 @OneToOne
的适当实体,并使用 @IndexedEmbedded
和 @ContainedIn
索引 A 和 B 的内容另一边。这将解决您使用本机 Hibernate Search 的问题。
我想我会尝试这样的事情:
@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 应该重新索引。