Search result lost after Session.merge on a child entity when using Multi-Tenancy

Description

When using Hibernate ORM multi-tenancy and `Session.merge()` on a child entity of one marked with `@Indexed`, the tenant information is lost in the Lucene index, making the `@Indexed` entity not appear in search results.

This seems to happen when the entity being merged has a collection of entities with a newly added child in it. If the merged entity's child collection has not changed or if it has children removed, the tenant information in the Lucene index seems preserved.

I've created a test case here (it could probably be even simpler):

A work-around would be appreciated (or a pointer to what is wrong with the use case).
The corresponding SO post:
https://stackoverflow.com/questions/57146004/hibernate-search-not-returning-results-on-newly-created-entities

Activity

Show:

Andrey Ustalakov July 26, 2019 at 4:32 PM
Edited

Thanks, I have gone with your first suggestion for a work around because I already had the ItemEntity fetched in the same session for a different reason. It seems to work as expected now. I do have other indexed types, but they are structured quite differently and don’t seem to be affected in the same way, so I will not use this workaround for them.

If you want to answer the SO question, I will accept it.

Yoann Rodière July 26, 2019 at 3:22 PM

I confirm it's a bug. Thanks a lot for taking the time to provide a reproducer, it was of tremendous help. I'm working on a fix.

Due to the location of the bug (deep inside implementation code), there's unfortunately not a lot you can do to work around the bug. The best you can do is to reindex explicitly just after the merge:

If you cannot realistically know in advance which entities are going to need to be reindex, there is potentially a hack you can use... but it's really a hack: be sure to test it properly. The idea is to ask Hibernate Search to perform an operation that won't change anything, but will have the side effect of initializing some internal structures properly.
After you started your transaction, just trigger a purge operation that you're absolutely sure won't have any effect, by using an entity ID that you're absolutely sure does not match any entity:

Then the internal structure for that entity type will be initialized properly, and @ContainedIn processing will work fine for the rest of the transaction.
If you have other indexed types, you will have to do the same for each type that could potentially be affected by your transaction.

Note the purge operation will still be executed, it's just that it won't have any effect since the ID does not match anything.

Fixed

Details

Assignee

Reporter

Sprint

Fix versions

Affects versions

Priority

Created July 26, 2019 at 2:01 PM
Updated September 18, 2019 at 12:59 PM
Resolved July 29, 2019 at 4:02 PM