In my project we are using Lucene and Hibernate Search/ORM 5.9.2. It works perfectly fine if a table is updated on database, same changes are reflected on ES indexes. But the index for a database view is not updated. Values are present under the database but not under the indexes.
What corresponding strategy/logic do I need to implement this through Hibernate search?
For any of the code referencing my implementation could be found under implemented code under the Java files.
Further, Lets assume I've 2 classes A & B and C is the view for A+B. And I'm storing C in my elastic indexes. Once A & B are updated under the Database, is it possible C will get updated? As I'm using Hibernate search+lucene annotations.
When a table is updated under database through Hibernate entities, Hibernate search is updating the same under the indexes. But this behavior is not happening for views as they are updated on the SQL Server side. Could this be achieved through Lucene/Hibernate search?
Hibernate Search is operating at the entity level. So it does not see the changes you make directly in your database.
For Hibernate Search to manage your index, you need to rely on entities.
There's really no option for it to do things differently as this is what it has been designed for.
If the changes are made to entities, you can implement your own listener layer to deal with C or make C an entity and implement a trigger dropping the update queries on it if your database can do it.
If the changes are made directly to the database, then you're out of luck with Hibernate Search. Or you have to trigger some service in your app, every time you make a change to the database to trigger the indexing.
BTW, do you need this view at the database level? Because if you only need it at the Elasticsearch level, you can make C a proper entity having a @OneToOne
to A and B and index the content of A and B using @IndexedEmbedded
and @ContainedIn
on the other side. That would solve your issue with native Hibernate Search.
I think I would try something like:
@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;
}
Then in A (same for 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;
}
}
Then when first creating A and B, you also need to create a C and inject it in A and B:
C c = new C();
a.setC( c );
b.setC( c );
em.persist( a );
em.persist( c );
Once this is done, whenever you update A or B, C should be reindexed thanks to the @ContainedIn
annotation.