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?