Hibernate会话线程

时间:2011-03-19 23:10:49

标签: multithreading hibernate asynchronous

我有关于Hibernate和延迟加载的问题。

背景: 我有一个Spring MVC Web应用程序,我使用Hibernate作为我的持久层。我正在使用OpenSessionInViewFilter使我能够在视图层中延迟加载实体。我正在扩展HibernateDaoSupport类并使用HibernateTemplate来保存/加载对象。一切都运作良好。到目前为止。

问题: 我有一个可以通过Web请求启动的任务。当请求被路由到控制器时,控制器将为此任务创建新的Runnable并启动线程以运行任务。因此原始线程将返回并且放入ThreadLocal(通过OpenSessionInViewFilter)的Hibernate会话不可用于Task的新线程。因此,当任务执行某些数据库操作时,我会得到臭名昭着的LazyInitializationException。

任何人都可以建议我可以为任务提供Hibernate会话的最佳方法吗?

感谢阅读。

3 个答案:

答案 0 :(得分:5)

Runnable设为一个Spring bean并在@Transactional上添加run注释。必须警告您,此异步任务不会在与Web请求相同的事务中运行。

请不要启动新主题,请使用pooling / executor。

答案 1 :(得分:1)

以下是有关如何在Runnable

中使用Hibernate会话的工作示例
@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()引用任何Spring托管bean,因此调度程序本身也没问题。任何其他Spring托管bean都可以正常工作。

答案 2 :(得分:0)

我是否理解正确,您想在完全专用的后台线程中执行某些操作,对吧?在这种情况下,我建议你根本不访问Hibernates OpenSessionInViewFilter以及该线程的进一步会话逻辑,因为它会被正确记录,在解耦线程中运行,因此在原始线程中加载信息(即,处理了最初的HttpRequest)。我认为在该线程中自己打开和关闭会话是明智的。

否则,您可能会质疑为什么要在分离的线程中运行该操作。可能是正常运行操作并在此期间为用户提供一些“加载”屏幕就足够了吗?