如何在Hibernate / Spring应用程序中处理后台线程

时间:2011-06-16 16:48:26

标签: java hibernate spring java-ee

我问我应该如何处理后台线程在Hibernate / Spring Web应用程序中执行涉及数据库的任务。

目前我正在使用以下拦截器,因此我可以使用@OpenSession注释我的线程运行方法,并且应该打开一个会话。这也应该适用于RMI请求,例如,在没有打开会话的情况下调用的任何其他方法。但是,我不确定代码是否正确,我面临的问题是,有时候会话才会被关闭并永远保持打开状态。

@Around("@annotation(openSession)")
    public Object processAround(ProceedingJoinPoint pjp, OpenSession openSession) throws Throwable {

        boolean boundResource = false;
        Session session = null;

        // Bind the session to the thread, if not already done
        if(TransactionSynchronizationManager.getResource(sessionFactory) == null) {
            log.debug("Opening Hibernate Session in method "+pjp.getSignature());

            session = SessionFactoryUtils.getSession(sessionFactory, true);
            TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
            boundResource = true;
        }

        // Invoke the annotated method
        Object ret;
        try {
            ret = pjp.proceed();
        }
        catch(Throwable t) {
            // Rethrows the Exception but makes sure the session will be closed
            SessionFactoryUtils.closeSession(session);
            log.debug("Closing Hibernate Session in method (Exception thrown) "+pjp.getSignature());
            throw t;
        }

        // If a resourc was bound by this method call, unbind it.
        if(boundResource) {
            //SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
            session.flush();
            SessionFactoryUtils.closeSession(session);

            log.debug("Closing Hibernate Session in method "+pjp.getSignature());
        }

        return ret;
    }

2 个答案:

答案 0 :(得分:1)

Hibernate会话和JDBC连接不是线程安全的。你应该坚持每个线程的连接和会话。

答案 1 :(得分:1)

是的,你建议的解决方案应该有效(我自己也做过非常相似的事情)。如果您只使用@Transactional,则每个事务都会获得一个新的EntityManager,如果您的后台线程有很多事务,则不一定是最佳的。