Sequence of flush(); clear(); commit(); can lead to LazyInitializationException
Description
Attachments
is fixed by
Activity

Fabio Massimo Ercoli August 13, 2019 at 9:19 AM
Hi, starting from the test you provided, I created a simple reproducer:
This test fails on the sample project.
I’m trying on Hibernate Search 6….

Yoann Rodière September 13, 2018 at 6:30 AM
Adding the full answer to this <make changes>; flush(); clear(); <repeat>;
problem, since it's potentially relevant here; copy-pasted from this stackoverflow answer:
The first, perhaps more correct, solution, would be for you to not use a single, big transaction, but multiple smaller ones. For example create a transaction for each chunk of 200 elements. Of course this means if a chunk fails, the previous chunks will still be in the database, but in many cases this might not matter, as you can just restart from where you failed, and the index would still be in sync with the database.
Spring gives you control over transactions using transaction templates, so you can manually start a new transaction for each chunk of 200 elements, or just refactor your code to put the @Transactional annotation at the right place. [There should be similar features in Java EE, I just don't know about them out of the top of my head.]
The second solution would be for you to still use a single, big transaction, but during the transaction periodically flush your changes, both to the database (which would be able to rollback the changes later if the transaction is aborted, don't worry) and to the index (which would not be able to rollback the changes later). This means in particular that if the transaction fails, you would have to restart everything and purge the index, because it would not be in sync with the database (which rolled back the changes) anymore.
You can find an example using periodic flushing in the documentation: https://docs.jboss.org/hibernate/search/5.10/reference/en-US/html_single/#search-batchindex-flushtoindexes
If you adapt the example, your code will look more or less like this:

Yoann Rodière September 13, 2018 at 6:13 AM
Digging this up... The correct sequence of commands when batching works would actually be: `flush();flushToIndexes(); clear(); commit();`. This should prevent any `LazyInitializationException` from happening.
Not to say we shouldn't try to detect it automatically and trigger the `flushToIndexes` ourselves, but I thought it could help.
Emmanuel Bernard January 23, 2015 at 8:09 AM
For info the sequence at bay is
We are trying to see if that sequence is common and makes sense in real life (i.e. aside from tests).
We could try and make that work but it would require to:
detect that a flush happens (some kind of flag that would be cleared by a search flush)
upon pre-clear, aggressively build the Document objects and keep them around
upon commit, build the remaining Documents (potential second flush) and write the old and new documents
That's a fairly heavy work. We would prefer not to have to spend that energy here if the use case is uncommon.
can you describe in more detail the use case you ahve for a em.flush(); em.clear(); commit(); sequence?

Gunnar Morling January 22, 2015 at 11:21 AM
Hi , after taking a closer look I realized the error isn't raised from within the discriminator but from your custom class bridge where you access the comments collection.
That exception actually makes sense, as you invoke EntityManager#clear()
prior to accessing it from within the class bridge, which makes the Post
entity unmanaged. As the comment collection hasn't been initialized before (just adding an element doesn't load the collection's state from the database) the exception is rightfully raised.
I adapted the test to actually navigate the lazy assocation from Country
to Language
within the discriminator and that worked as expected, i.e. the language entity is fetched from the database.
So I'm going to close this issue as "Cannot re-produce". Feel free to re-open if you have a test case which actually causes a LazyInitializationException
within the discriminator (and which is not caused by manually detaching objects with unloaded lazy references). Thx!
Details
Details
Assignee

Reporter

I have a discriminator that throws a lazyloading exception in some cases:
I'm trying to isolate the condition, but I wanted to note this here.