3

休止状態を使用する 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、クラスが最初にロードされたときにメンバーが実際に1回だけ初期化されるようですJVMが、何らかの理由で、異なるスレッドがgetSession()異なるセッションを使用するメソッドにアクセスするときに発生します。スレッドが最初にこのクラスにアクセスする (Session) threadLocal.get();と、null が返されますが、予想どおり、他のすべてのアクセス要求は同じセッションを生成します。threadLocal変数が final であり、メソッドが上記のコンテキストでのみ使用されるため、これがどのように発生するかはわかりません(別の部分でthreadLocal.set(session)遭遇したため、null 以外のセッションを生成する必要があると 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 -->

助けていただければ幸いです。もちろん、ご不明な点がございましたら、喜んでお答えいたします。イッタイ

4

1 に答える 1

7

あなたはその目的を知っていますThreadLocalか?

ドキュメントから:

このクラスは、スレッドローカル変数を提供します。これらの変数は、(getまたはsetメソッドを介して)1つにアクセスする各スレッドが、変数の独自の独立して初期化されたコピーを持っているという点で、通常の対応する変数とは異なります。ThreadLocalインスタンスは通常、状態をスレッド(たとえば、ユーザーIDまたはトランザクションID)に関連付けたいクラスのプライベート静的フィールドです。

コードが実行するように指示されているため、スレッドごとに異なるHibernateセッションを取得しています。

さて、これが良いことであるかどうかについて実際にコメントすることはできません-多くの場合、それは合理的に賢明ですが。結局のところ、2つのスレッドが同じセッションを共有し、互いのトランザクションと対話することは望ましくありませんか?

于 2010-04-27T19:02:51.917 に答える