我创建了一个 Quartz Job,它在我的 JBoss 服务器的后台运行,负责定期更新一些统计数据(加上一些数据库标志)
加载和持久化我正在使用 Hibernate 4。除了一个小问题,一切都很好。
整个线程,即 Job 被包裹在一个单一的事务中,随着时间的推移(随着数据量的增加)变得巨大并且令人担忧。我试图将这个单一的大事务分解成多个小事务,这样每个事务只处理一个子组数据。
问题:我非常笨拙地尝试将代码包装到循环中,并在循环的开始/结束处开始/结束事务。正如我所料,它没有用。我一直在寻找各种论坛以找出解决方案,但没有遇到任何表明在单个会话中管理多个事务(一次只有一个事务将处于活动状态)的任何内容。
我对休眠比较陌生,如果有任何帮助可以为我指明实现这一目标的方向,我将不胜感激。
更新:添加代码演示了我想要实现的目标以及当我说闯入多个事务时的意思。并在执行此操作时进行堆栈跟踪。
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、会话和事务的理解。似乎在创建会话时,它会附加到线程并在线程生命周期内或调用提交或回滚时存在。因此,当提交第一个事务时,会话将被关闭,并且在线程的剩余生命周期中不可用。
我的问题仍然存在:我们如何在一个会话中进行多个事务?