我创建了一个Quartz Job,它在JBoss服务器的后台运行,负责定期更新一些统计数据(加上一些数据库标志)
加载并坚持我正在使用Hibernate 4.一切正常,除了一个hicknate。
整个线程,即Job被包装在单个事务中,在一段时间内(随着数据量的增加)变得巨大并且担心一些。我试图将这个单个大型事务分解为多个小事务,这样每个事务处理只会处理一组子数据。
问题:我非常蹩脚地将代码包装到循环中,并在循环的开始/结束时开始/结束事务。正如我所料,它没有用。我一直在寻找各种论坛以找出解决方案,但没有发现任何表明在一个会话中管理多个交易的事情(一次只有一个交易活动)。
我对hibernate相对较新,并且非常感谢任何帮助我指明实现这一目标的方向。
更新:添加代码演示了我想要实现的目标,并且当我说进入多个事务时意味着什么。执行此操作时堆栈跟踪。
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.");
以下是我执行此Job
时遇到的异常堆栈跟踪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,会话和事务的内容。似乎在创建会话时,它会附加到线程并贯穿线程生命或调用commit或rollback。因此,当提交第一个事务时,会话正在关闭,并且在其余的线程生命中不可用。
我的问题仍然存在:我们如何在一个会话中拥有多个交易?
答案 0 :(得分:2)
更多细节会很棒,有些例子,但我想我应该能够帮助你写下这里所写的内容。
有一个静态SessionFactory(内存很大) 您的交易也需要这样的事情。
SomeClass object = new SomeClass();
Session session = sessionFactory().openSession() // create the session object
session.beginTransaction(); //begins the transaction
session.save(object); // saves the object But REMEMBER it isn't saved till session.commit()
session.getTransaction().commit(); // actually persisting the object
session.close(); //closes the transaction
这是我使用我的交易的方式,我不确定我是否一次做多次交易。但是与内存中的SessionFactory相比,会话对象重量轻。
如果您希望一次保存更多对象,则可以在一个事务中执行此操作。
SomeClass object1 = new SomeClass();
SomeClass object2 = new SomeClass();
SomeClass object2 = new SomeClass();
session.beginTransaction();
session.save(object1);
session.save(object2);
session.save(object3);
session.getTransaction().commit(); // when commit is called it will save all 3 objects
session.close();
希望以某种方式提供帮助或指出正确的方向。 我认为你可以配置程序来压缩事务。 :)
修改的 这是一个很棒的youtube教程。这家伙真的为我打破了它。