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

Itt*_*tai 3 java session multithreading hibernate thread-local

我有一个使用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.
Run Code Online (Sandbox Code Playgroud)

现在从我的测试看来,threadLocal当第一次加载类时,该成员确实只被初始化了一次JVM但由于某种原因,当不同的线程访问getSession()它们使用不同会话的方法时.当线程首次访问此类时 (Session) threadLocal.get();将返回null,但正如预期的那样,所有其他访问请求将返回相同的会话.我不确定这是怎么发生的,因为threadLocal变量是最终的,并且该方法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 -->
Run Code Online (Sandbox Code Playgroud)

我很感激任何帮助,当然如果有人有任何问题我会很乐意澄清.以太

Jon*_*eet 7

你知道的目的ThreadLocal什么?

来自文档:

该类提供线程局部变量.这些变量与它们的正常对应物的不同之处在于,访问一个变量的每个线程(通过其get或set方法)都有自己独立初始化的变量副本.ThreadLocal实例通常是希望将状态与线程(例如,用户ID或事务ID)相关联的类中的私有静态字段.

您正在为每个线程准确地获得不同的Hibernate会话,因为这是您的代码所要做的.

现在,我们无法评论这是否是一件好事 - 尽管在许多情况下它是合情合理的.毕竟,你不希望两个线程共享同一个会话并与彼此的交易进行交互,不是吗?