【问题标题】:I don't get session for Hibernate in thread for an web application in Tomcat我没有在 Tomcat 中的 Web 应用程序线程中获得 Hibernate 会话
【发布时间】:2014-07-28 06:57:12
【问题描述】:

我有一个带有 Tomcat 的 Web 应用程序。我正在使用一些线程而不是在控制器中执行。在这个线程中,我执行其他线程。

这个线程需要与 Hibernate 进行会话,但是当我执行一些查询时它不起作用,尽管我在每个线程的“运行”方法中打开了一个新会话。

当我在 Tomcat 外部执行这段代码时,它就像一个简单的 java main 一样工作。所以,看起来我对Tomcat做错了。 我想这可能是因为 OpenSessionInViewFilter。我收到关于当前线程没有会话的错误。

我得到的例外是:

org.hibernate.HibernateException: No Session found for current thread
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:941)

我的 web.xml

<filter>
        <filter-name>sessionView</filter-name>
        <filter-class>
            org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>sessionView</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

我的控制器

 @Override
    protected ModelAndView onSubmit(final HttpServletRequest request,
            final HttpServletResponse response, final Object command, final BindException errors)
            throws Exception {          
        MyThread thread = new ExecuteETLThread();
        thread.start();
        ...
    }

我的线程:

public final class MyThread extends AbstracThread {

 @Override
    public void runThread() {
        try {
            //I get an exception here. I just put this senstence here for checking.
            context.getConfigurationDAO().get("A");            
            //Normally, I open more threads here that they connect with hibernate and fail.
            //otherThread.start();
        } catch (final Exception e) {
            LOG.error(e);
        }
    }

抽象线程:

public abstract class AbstractThread extends Thread {
    @Override
    public final void run() {
        try {
            OpenSessionInView.openSession();
            runThread();
        } catch (final Exception e) {
            LOG.error("Error running BidoopThread", e);
        } finally {
            OpenSessionInView.closeSession();
        }
    }
    public abstract void runThread();
}

使用 Hibernate 打开会话。

public final class OpenSessionInView {
    public static void openSession() {
        final SessionFactory sf = Factory.getSessionFactory();

        final Session session = sf.openSession();
        session.setFlushMode(FlushMode.COMMIT);
        TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
    }

    public static void closeSession() {
        final SessionFactory sf = Factory.getSessionFactory();
        final SessionHolder sessionHolder =
                (SessionHolder) TransactionSynchronizationManager.unbindResource(sf);
        SessionFactoryUtils.closeSession(sessionHolder.getSession());
    }

【问题讨论】:

  • 为什么要对 JavaEE 应用程序进行多线程处理?这是您使用 Tomcat 免费获得的东西之一..
  • 线程执行一些可能需要一段时间的 MapReduce 代码。所以,我不想让用户等待答案。有意义吗?
  • 还有其他方法吗?
  • 您可以使用Spring@Async 注释来避免手动线程处理。另外,我认为有问题的错误通常与在没有事务上下文的情况下执行一些 JPA 调用有关。

标签: java multithreading hibernate tomcat


【解决方案1】:

OpenSessionInViewFilter 和 Spring 的 EntityManager 委托都使用 ThreadLocal 来存储真正的 EntityManager 实现。每次发起请求时,它们都会在此请求的线程中将 EntityManager 绑定到此 ThreadLocal。因此 EM 不会绑定到您手动创建的线程。您应该观察您的堆栈跟踪并找出 spring 在哪里寻找 EM(或会话)。根据您提供的堆栈跟踪,学习 SpringSessionContext 以找到手动绑定会话的方法。此外,您还需要在线程完成时执行一些工作来清理会话。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-16
    • 2018-12-27
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 2010-10-27
    • 1970-01-01
    • 2010-12-12
    相关资源
    最近更新 更多