Java Multithreading with Hibernate Session and Spring

Ori Berkovitch
2 min readMay 6, 2022

--

Working with multithreading on Spring and Hibernate can be quite frustrating, as the code ability to actually query and influence the database through Hibernates relies on the hidden Session and concept of “Unit of Work” abstracted by Spring’s strong infrastructures.

If we try to spawn a Thread from a @Scheduled process, or try to create a database transaction while handling an http request — we probably will encounter the common errors:

  • LazyInitializationException
  • Could not obtain transaction-synchronized Session for current thread

While these have their respected place among theorists — if we simply want to solve these and make things “work”, we just have a adhere to the basic concept of “working with the infrastructure” rather then “against the infrastructure”.

General Setup

To set up working with @Async please see reference:

https://www.baeldung.com/spring-async

Threads vs @Async

Creating Java threads using the Thread base class — is not natural to the Spring lifecycle and Hibernate session. Meaning, the session starts at the http handler or at the @Scheduled endpoint, etc — and is maintained by Spring on the running thread. If you wish to be able to both work multithreaded AND use hibernate’s session — you have to spawn threads using @Async calls — directly from the running thread.

Notice the 2 most important rules here: “@Async has two limitations

  • It must be applied to public methods only.
  • Self-invocation — calling the async method from within the same class — won’t work.”
Illustration of the required component for @Aysnc

From the description and the illustration, remember — the async function must be placed in a different component from the caller.

Blocking and waiting for threads

When we use the Thread class, and extend it, we usually use the function join() to attach to the process and wait for the results. The equivalent of this when using @Async would be the use of the function result as a Future object. Specifically, if the Async function should have returned a String — you should have it return a Future<String> instead. And for the result, instead of returning a String result — you return

return new AsyncResult<String>(“your-result-here”);

In the example below, we have used Boolean — as a replacement of a void function. We just needed to return something, so the Async thread can be in our control

Illustration of values returned from an Async function in Spring

--

--