代码之家  ›  专栏  ›  技术社区  ›  Ittai

为什么我的应用程序中的每个线程都使用不同的休眠会话?

  •  3
  • Ittai  · 技术社区  · 16 年前

    我有一个使用Hibernate的Web应用程序,由于某种原因,每个线程(httpRequest或其他与排队相关的线程)都使用不同的会话。 我已经实现了 HibernateSessionFactory 类,如下所示:

    public class HibernateSessionFactory {
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    private  static Configuration configuration = new AnnotationConfiguration();    
    private static org.hibernate.SessionFactory sessionFactory;
    static {
        try {
            configuration.configure(configFile);
            sessionFactory = configuration.buildSessionFactory();
        } catch (Exception e) {}
    }
    private HibernateSessionFactory() {}
    public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        if (session == null || !session.isOpen()) {
    if (sessionFactory == null) {
        rebuildSessionFactory();//This method basically does what the static init block does
    }
    session = (sessionFactory != null) ? sessionFactory.openSession(): null;
    threadLocal.set(session);
    }
       return session;
    }
    //More non relevant methods here.
    

    从我的测试来看 threadLocal 当类首次由 JVM 但出于某种原因,当不同的线程访问 getSession() 方法他们使用不同的会话。当线程第一次访问此类时 (Session) threadLocal.get(); 将返回空,但如预期的那样,所有其他访问请求将触发同一会话。我不知道这是怎么发生的 线程本地 变量是最终的方法 threadLocal.set(session) 只在上面的上下文中使用(我是99.9%的人,肯定必须建立一个非空会话,因为我会遇到一个 NullPointerException 在我的应用程序的另一个部分)。

    我不确定这是否相关,但这些是我的主要部分 hibernate.cfg.xml 文件:

    <hibernate-configuration>
    <session-factory>
    <property name="connection.url">someURL</property>
    <property name="connection.driver_class"> com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
    <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
    
    <property name="hibernate.connection.isolation">1</property> 
    
    <property name="hibernate.connection.username">User</property>
    <property name="hibernate.connection.password">Password</property>
    <property name="hibernate.connection.pool_size">10</property>
    
    <property name="show_sql">false</property>
    <property name="current_session_context_class">thread</property>
    <property name="hibernate.hbm2ddl.auto">update</property>
    
    <property name="hibernate.cache.use_second_level_cache">false</property>
    <property name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    <!-- Mapping files -->
    

    我很感谢你给予我的帮助,当然,如果有人有任何问题,我很乐意澄清。 伊泰

    1 回复  |  直到 13 年前
        1
  •  7
  •   Jon Skeet    16 年前

    你知道吗 目的 属于 ThreadLocal ?

    从 the docs :

    此类提供本地线程 变量。这些变量不同于 它们的正常对应物 访问一个的线程(通过其get 或set方法)有自己的, 独立初始化的 变量。线程本地实例是 通常是中的私有静态字段 希望关联状态的类 使用线程(例如,用户ID或 事务ID)。

    您将为每个线程获得不同的休眠会话,这正是您的代码所说的。

    现在,我们不能真正评论这是否是一件好事——尽管在许多情况下这是合理的。毕竟,您不希望两个线程共享同一个会话并与彼此的事务交互,是吗?