Hibernate search to work on the same index for two different Entities of same table

#1

In our project, we are having more than one entities for the same table. Multiple entities are needed to cater performance restriction which arise due to large no of associations on main entity. So, different entities are created with different associations.
So, ReceivableInstructionMain is main entity and ReceivableInstructionLE is lighter entity of same table.
Now, when a record is saved for the first time, it is done using ReceivableInstructionMain entity but it is possible that same record is updated with ReceivableInstructionLE entity.
So, how to manage same index for both entities so that changes done using ReceivableInstructionLE entity are availble within index using ReceivableInstructionMain entity also.

0 Likes

#2

Hibernate Search requires the full entity data when updating a document; there is no support for “partial document updates” yet. That’s something we would like to implement one day (see https://hibernate.atlassian.net/browse/HSEARCH-2888), but it’s a complex topic.

EDIT: what’s below was wrong; turns out there’s a safety that makes sure that when two entities share the same index, we do not just differentiate them by their id, but also by their class name. So you would end up with duplicates of documents… See below for another solution that involves changing the approach on the ORM side.

For that reason, indexing ReceivableInstructionLE directly would only be possible if:

  1. You make sure that all indexed data is accessible from both entities.
  2. You make sure that both ReceivableInstructionMain and ReceivableInstructionLE have the exact same mapping.

If both those conditions are met, I think that you should be able to annotate both entities with @Indexed(index = "theSameIndexNameForBoth") and Hibernate Search should update the index according to changes from both entities. You’ll have to try, but I think it should work.

Some words of warning, though:

  1. If, in a single transaction, you load and change the same entity (same ID) using both ReceivableInstructionMain and ReceivableInstructionLE, I’m pretty sure things will go wrong. But then I suppose it will go wrong in Hibernate ORM as well.
  2. We intend to remove support for pushing multiple entity types to the same index in Hibernate Search 6, due to internal changes in Search and to limitations introduced in Elasticsearch 6. We may restore it in a later version, but that’s not certain because quite some work will be needed.

Alternatively, you could change your approach on the Hibernate ORM side:

Simply using lazy association

You could remove ReceivableInstructionLE and make all the associations from Main that weren’t in LE lazy. Unless you try to load them, they shouldn’t affect performance anymore.

If, in some queries, you need to load some associations eagerly, you can use dynamic fetching.

Using entity graphs

You could explore the entity graphs feature, which theoretically allows you to define, for a given query, which associations should be loaded exactly. Think of it like a more powerful version of dynamic fetching, configured application-wide. I’ve never used it personally, but it seems to fit your use case: you should be able to remove ReceivableInstructionLE, use ReceivableInstructionMain everywhere, and set the entity graph when fetching entities.

Keeping ReceivableInstructionLE

In both cases, you could even imagine turning ReceivableInstructionLE into a wrapper that only exposes the proper data, delegating to an inner ReceivableInstructionMain instance. That way you wouldn’t have to change all your code, just querying code: you’d add an entity graph hint or fetch hint and wrap results in ReceivableInstructionLE.

0 Likes

#3

Thanks yrodiere for your response.
Will try with Single Entity only after removing ReceivableInstructionLE

0 Likes

#4

Hi Yrodiere,

We are trying to implement the solution by defining all OneToOne associations in ReceivableInstructionMain as Lazy.
There are 25 associations marked as Lazy. Now, in a scenario we need to load 18 associations along with main entity, so we defined entity graph with these 18 entities.
Each of these 18 entities further contain OneToOne associations.
Now, when select query fired on ReceivableInstructionMain, actual select statement contain left outer join to fetch all 18 associations and other associations from these associations.

Now, a strange behavior is happening in which 1-2 random association from any of these 18 associations are getting selected via different select statement.

Could you please let me know why separate select is getting fired for these associations other than main left outer join query?

0 Likes

#5

Honestly no, without looking at the code I don’t really know.

I can only guess: maybe your entity graph is incomplete and thus the associations are still lazy; maybe there are some hard limits to the number of joins in a query (doubtful); maybe there’s a bug in ORM?

You’ll probably get better answers by asking in the Hibernate ORM category and giving a bit more context. Giving the code of your entities, the code that executes the query, and perhaps the SQL logs, would already help a lot.

0 Likes