在单个休眠会话中创建多个事务

时间:2013-05-19 06:06:15

标签: java hibernate postgresql transactions

我创建了一个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。因此,当提交第一个事务时,会话正在关闭,并且在其余的线程生命中不可用。

我的问题仍然存在:我们如何在一个会话中拥有多个交易?

1 个答案:

答案 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教程。这家伙真的为我打破了它。

Hibernate Tutorials