JBoss サーバーでバックグラウンドで実行される Quartz ジョブを作成し、一定の間隔でいくつかの統計データを更新する責任があります (いくつかのデータベース フラグと組み合わせて)
をロードして永続化するには、Hibernate 4 を使用しています。
スレッド全体、つまりジョブは単一のトランザクションにラップされ、一定期間 (データ量が増加するにつれて) 巨大になり、心配になります。各トランザクションがデータのサブグループのみを処理するように、この単一の大きなトランザクションを複数の小さなトランザクションに分割しようとしています。
問題: コードをループにラップし、ループの開始/終了時にトランザクションを開始/終了しようとしました。思った通り、うまくいきませんでした。解決策を見つけるためにさまざまなフォーラムを見回してきましたが、単一のセッションで複数のトランザクションを管理することを示すものは見つかりませんでした (一度に 1 つのトランザクションのみがアクティブになります)。
私は休止状態に比較的慣れていないため、これを達成するための方向性を示す助けをいただければ幸いです。
更新: コードを追加することで、私が達成しようとしていることと、複数のトランザクションに分割すると言う意味が示されます。そしてこれを実行するとスタックトレース。
log.info("Starting Calculation Job.");
List<GroupModel> groups = Collections.emptyList();
DAOFactory hibDaoFactory = null;
try {
hibDaoFactory = DAOFactory.hibernate();
hibDaoFactory.beginTransaction();
OrganizationDao groupDao = hibDaoFactory.getGroupDao();
groups = groupDao.findAll();
hibDaoFactory.commitTransaction();
} catch (Exception ex) {
hibDaoFactory.rollbackTransaction();
log.error("Error in transaction", ex);
}
try {
hibDaoFactory = DAOFactory.hibernate();
StatsDao statsDao = hibDaoFactory.getStatsDao();
StatsScaledValuesDao statsScaledDao = hibDaoFactory.getStatsScaledValuesDao();
for (GroupModel grp : groups) {
try {
hibDaoFactory.beginTransaction();
log.info("Performing computation for Group " + grp.getName() + " ["
+ grp.getId() + "]");
List<Stats> statsDetail = statsDao.loadStatsGroup(grp.getId());
// Coputing Steps here
for (Entry origEntry : statsEntries) {
entry.setCalculatedItem1(origEntry.getCalculatedItem1());
entry.setCalculatedItem2(origEntry.getCalculatedItem2());
entry.setCalculatedItem3(origEntry.getCalculatedItem3());
StatsDetailsScaledValues scValues = entry.getScaledValues();
if (scValues == null) {
scValues = new StatsDetailsScaledValues();
scValues.setId(origEntry.getScrEntryId());
scValues.setValues(origEntry.getScaledValues());
} else {
scValues.setValues(origEntry.getScaledValues());
}
statsScaledDao.makePersistent(scValues);
}
hibDaoFactory.commitTransaction();
} catch (Exception ex) {
hibDaoFactory.rollbackTransaction();
log.error("Error in transaction", ex);
} finally {
}
}
} catch (Exception ex) {
log.error("Error", ex);
} finally {
}
log.info("Job Complete.");
以下は、このジョブの実行時に取得する例外スタックトレースです
org.hibernate.SessionException: Session is closed!
at org.hibernate.internal.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:127)
at org.hibernate.internal.SessionImpl.createCriteria(SessionImpl.java:1555)
at sun.reflect.GeneratedMethodAccessor469.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)
at $Proxy308.createCriteria(Unknown Source)
at com.blueoptima.cs.dao.impl.hibernate.GenericHibernateDao.findByCriteria(GenericHibernateDao.java:132)
at com.blueoptima.cs.dao.impl.hibernate.ScrStatsManagementHibernateDao.loadStatsEntriesForOrg(ScrStatsManagementHibernateDao.java:22)
... 3 more
Hibernate、セッション、およびトランザクションについてこれまで読んだことから、私の理解に。セッションが作成されると、スレッドにアタッチされ、スレッドの存続期間中、またはコミットまたはロールバックが呼び出されたときに存続するようです。したがって、最初のトランザクションがコミットされると、セッションは閉じられ、スレッドの残りの期間は使用できなくなります。
私の疑問は残ります: 1 つのセッションで複数のトランザクションを行うにはどうすればよいでしょうか?