Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate Session Threading

I have a problem regarding Hibernate and lazy loading.

Background: I have a Spring MVC web app, I use Hibernate for my persistence layer. I'm using OpenSessionInViewFilter to enable me to lazy load entities in my view layer. And I'm extending the HibernateDaoSupport classes and using HibernateTemplate to save/load objects. Everything has been working quite well. Up until now.

The Problem: I have a task which can be started via a web request. When the request is routed to a controller, the controller will create a new Runnable for this task and start the thread to run the task. So the original thread will return and the Hibernate session which was put in ThreadLocal (by OpenSessionInViewFilter) is not available to the new thread for the Task. So when the task does some database stuff I get the infamous LazyInitializationException.

Can any one suggest the best way I can make a Hibernate session available to the Task?

Thanks for reading.

like image 415
C0deAttack Avatar asked Mar 19 '11 23:03

C0deAttack


2 Answers

Make your Runnable a Spring bean and add @Transactional annotation over run. You must be warned thou that this asynchronous task won't run in the same transaction as your web request.

And please don't start new thread, use pooling/executor.

like image 88
Tomasz Nurkiewicz Avatar answered Oct 21 '22 02:10

Tomasz Nurkiewicz


Here is a working example on how to use the Hibernate session inside a Runnable:

@Service
@Transactional
public class ScheduleService {

    @Autowired
    private SessionFactory      sessionFactory;

    @Autowired
    private ThreadPoolTaskScheduler     scheduler;

    public void doSomething() {

        ScheduledFuture sf = scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(scheduler);
                final Session session = sessionFactory.openSession();
                // Now you can use the session
            }
        }, new CronTrigger("25 8 * * * *"));
    }
}

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext() takes a reference to any Spring managed bean, so the scheduler itself is fine. Any other Spring managed bean would work as well.

like image 31
yglodt Avatar answered Oct 21 '22 04:10

yglodt