If we take for example some transactional Spring code:
@Transactional // a new session was created here
public void someTransactionalMethod() {
...
}
This means that the spring container needs to create a session, if none was already present. with this two questions come to mind:
- where to store the session just created
- where to go and see if an session was already created, and if so retrieve it?
The session that is used by the Spring aspect to ensure @Transactional
functionality needs to be stored somewhere other than the application code.
This could be stored anywhere: in a singleton, in the session, or in a ThreadLocal variable, effectively bounding it to the thread executing the application code.
Every thread as a map where we can store variables, and ThreadLocal
is a convenient abstraction around it, allowing to create thread-scoped variables.
There is no technical constraint to bind the session to a thread, it's just a design decision that is frequent: give the variable the narrowest scope possible, avoid global variables, etc.
In the case of applications running in servlet containers, there is guarantee that for a given HTTP request, the same thread will be used to treat the whole request up until the generation of the response.
In other environments the same guarantee is made, so the designers of the most frequently used transaction managers, JpaTransactionManager and HibernateTransactionManager decided to use the Thread as the place where the entity manager / hibernate session is stored.
Binding the session/entity manager to a thread using a ThreadLocal
variable is a simple way to ensure that no multi-threaded bugs would ever occur in the transaction management code, it's a concurrent programming strategy known as Thread Confinement.