java - Swingアプリケーションでマルチスレッドを使用するHibernate

java multithreading hibernate swing lazy-loading

マルチスレッドでの休止状態の問題に直面しています。

POJOクラスがいくつかある、swingベースのアプリケーションを開発しています。クラス間の関係:カテゴリーにはプロトコルのセットがあり、プロトコルにはステップのセットがあり、ステップにはモードのセットがあります。すべてのコレクションは、fetch = FetchType.LAZYを使用して遅延ロードされます。アプリケーションの単一セッションを維持しています。すべてのカテゴリのリストを取得した後、カテゴリリストでいくつかの操作を実行するためにいくつかのスレッドを開始する必要があります。ここでは、LazyInitializationExceptionが発生しています。テストコードは次のとおりです。

final List<Category> cats = protocolDao.getCategoryList();
for (int i = 0; i < 10; i++) {
new Thread("THREAD_" + i) {
    public void run() {
    try {
        for (Category category : cats) {
        Set&lt;Protocol> protocols = category.getProtocols();
            for (Protocol protocol : protocols) {
            Set&lt;Step> steps = protocol.getStep();
            for (Step step : steps) {
                step.getModes());
            }
            }
        }
        System.out.println(Thread.currentThread().getName()+"SUCCESS"  ;
        } catch (Exception e) {
        System.out.println("EXCEPTION ON " + Thread.currentThread().getName());
        }
    };
    }.start();
}




daoメソッドは次のとおりです。

public List&lt;Category> getCategoryList() throws ProtocolException {
    try {
        Transaction transaction = session.beginTransaction();
    List list = session.createCriteria(Category.class)
        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
        .addOrder(Order.asc("categoryposition")).list();
    transaction.commit();
    return list;
    } catch (Exception e) {
       throw new ProtocolException(e);
    }
}




上記のコードを実行しようとすると、一部のスレッドで次の例外が発生します。

SEVERE: illegal access to loading collection
org.hibernate.LazyInitializationException: illegal access to loading collection
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:363)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
    at org.hibernate.collection.PersistentSet.toString(PersistentSet.java:332)
    at java.lang.String.valueOf(String.java:2826)
    at java.lang.StringBuilder.append(StringBuilder.java:115)
    at com.mycomp.core.protocol.dao.test.TestLazyLoading$1.run(TestLazyLoading.java:76)


したがって、一部のタスクは完了していません。複数のスレッドが同じカテゴリリストで動作することを回避できません(単一のスレッドで正常に動作します)。すべてのスレッドは独自のタスクを実行する必要があります。データベースが大きすぎるため、遅延読み込みを回避できません。同じカテゴリリストの複数のスレッドをどのように処理できるようになるでしょうか?
答え
エンティティを取得するスレッドのみがそれらを使用することを確認する必要があります。 get IDがあり、IDメソッドまたは同様の方法で取得する場合:

final int[] catIds = protocolDao.getCategoryIds();
for (int i : catIds) {
  new Thread("THREAD_" + i) {
    public void run() {
      Category category = protocolDao.getCategory(i);
      Set<Protocol> protocols = category.getProtocols();
      for (Protocol protocol : protocols) {
        Set<Step> steps = protocol.getStep();
          for (Step step : steps) {
            step.getModes());
          }
      }
    };
  }.start();
}
関連記事