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

发布于 2024-08-30 16:00:50 字数 2651 浏览 7 评论 0原文

我有一个使用休眠的网络应用程序,由于某种原因,每个线程(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 成员确实只在该类首次由 加载时初始化一次。 code>JVM 但由于某种原因,当不同的线程访问 getSession() 方法时,它们使用不同的会话。当线程首次访问此类时,(Session) threadLocal.get(); 将返回 null,但正如预期的那样,所有其他访问请求都将产生相同的会话。我不确定这是如何发生的,因为 threadLocal 变量是最终的,并且方法 threadLocal.set(session) 仅在上述上下文中使用(我' m 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 -->

我将不胜感激任何帮助,当然如果有人有任何问题我会很高兴澄清一下。 一泰

I have a web-application which uses hibernate and for some reason every thread (httprequest or other threads related to queueing) uses a different session.
I've implemented a HibernateSessionFactory class which looks like this:

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.

Now from my testing it seems that the threadLocal member is indeed initialized only once when the class is first loaded by the JVM but for some reason when different threads access the getSession() method they use different sessions. When a thread first accesses this class (Session) threadLocal.get(); will return null but as expected all other access requests will yeild the same session. I'm not sure how this can be happening as the threadLocal variable is final and the method threadLocal.set(session) is only used in the above context (which I'm 99.9% sure has to yeild a non null session as I would have encountered a NullPointerException at a different part of my app).

I'm not sure this is relevant but these are the main parts of my hibernate.cfg.xml file:

<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 -->

I'd appreciate any help granted and of course if anyone has any questions I'd be happy to clarify.
Ittai

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

盛装女皇 2024-09-06 16:00:50

您知道 ThreadLocal 的用途吗?

来自文档

该类提供线程局部
变量。这些变量不同于
他们的正常对应物是每个
访问一个线程(通过其 get
或设置方法)有自己的,
独立初始化的副本
多变的。 ThreadLocal 实例是
通常是私有静态字段
希望关联状态的类
带有一个线程(例如,用户 ID 或
交易ID)。

您将为每个线程获得不同的 Hibernate 会话,因为这就是您的代码所说的操作。

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

Are you aware of the purpose of ThreadLocal?

From the docs:

This class provides thread-local
variables. These variables differ from
their normal counterparts in that each
thread that accesses one (via its get
or set method) has its own,
independently initialized copy of the
variable. ThreadLocal instances are
typically private static fields in
classes that wish to associate state
with a thread (e.g., a user ID or
Transaction ID).

You're getting a different Hibernate session for each thread precisely because that's what your code says to do.

Now, we can't really comment on whether this a good thing or not - although in many cases it's reasonably sensible. After all, you wouldn't want two threads to share the same session and interact with each other's transactions, would you?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文