为什么我的应用程序中的每个线程都使用不同的休眠会话?
我有一个使用休眠的网络应用程序,由于某种原因,每个线程(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您知道 ThreadLocal 的用途吗?
来自文档:
您将为每个线程获得不同的 Hibernate 会话,因为这就是您的代码所说的操作。
现在,我们无法真正评论这是否是一件好事 - 尽管在许多情况下这是相当明智的。毕竟,您不希望两个线程共享同一会话并与彼此的事务交互,不是吗?
Are you aware of the purpose of
ThreadLocal
?From the docs:
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?