We use Hibernate through JPA and Spring to manage object persistence in our web application. We use open-session-in-view pattern to create sessions for threads responding to http requests. We also use some threads that are not generating views - they just wake up from time to time to do their job. That generates problems because they don't have session opened by default so they generate exceptions like
org.hibernate.SessionException: Session is closed! 
or
 could not initialize proxy - no Session
We found out that if every background thread invokes its logic in a method annotated with @Transactional there are no exceptions of this kind as @Transactional makes sure that thread has session when it's inside the transaction.
It solved problems for some time but I don't think that it's a good solution - making long-running methods transactional causes problems because other threads can't see changes made in database until the transaction is committed.
I created a java-pseudocode example to better illustrate my problem:
public class FirstThread {
    ...
    @Transactional
    public void processQueue() {
        for(element : queue){
            if(elementCanBeProcessed(element)){
                elementDao.saveIntoDatabase(element);
                secondThread.addToQueue(element.getId());
            }
        }
    }
    private boolean elementCanBeProcessed(element){
        //code that gets a few objects from database and processes them
    }
}
If I annotate the whole processQueue method with @Transactional the changes made in 
elementDao.saveIntoDatabase(element);
won't be seen in secondThread until the transaction is committed (so until the whole queue is processed). If I don't do that then the thread won't have session inside the elementCanBeProcessed and it won't  be able to access the database. I also can't annotate elementCanBeProcessed instead because it's a private method in this class and I would have to move this into another class so that Spring proxy could work. 
Is it possible to bind session to thread without making the whole method transactional? How should I manage sessions and transactions in background threads like that one?
Here is the code I wrote after reading Amir Moghimi's answer. It seems a little bit 'hacky' because the documentation says that neither EntityManagerHolder nor TransactionSynchronizationManager should be used directly by a typical application code.
@Service
public class DatabaseSessionManager {
    @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;
    public void bindSession() {
        if (!TransactionSynchronizationManager.hasResource(entityManagerFactory)) {
            EntityManager entityManager = entityManagerFactory.createEntityManager();
            TransactionSynchronizationManager.bindResource(entityManagerFactory, new EntityManagerHolder(entityManager));
        }
    }
    public void unbindSession() {
        EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager
                .unbindResource(entityManagerFactory);
        EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
    }
}
It seems to be working - the session is bound to my thread between bindSession() and unbindSession() calls and I don't have to create a transaction to achieve it. 
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With