使用@Transactional属性进行手动提交

时间:2012-03-12 01:40:53

标签: java spring hibernate

我使用spring + hibernate模板来处理实体。有大量的实体同时被加载,所以我从hibernate模板中检索一个迭代器。

每个实体都应作为一个单独的工作单元处理。我试图将实体处理放在一个单独的事务中(propagation = REQUIRED_NEW)。但是我以异常结束,声明代理被限制为两个会话。这是由于用于迭代器延迟加载的挂起事务。我使用相同的bean进行延迟加载和处理实体。 (可能它应该被重构为两个独立的daos:一个用于延迟加载,一个用于处理?)

然后我尝试使用在处理每个实体后提交的单个事务。在这里好多了,在实体处理过程中没有异常,但是在处理完成并且方法返回之后,从spring事务管理代码抛出异常。

@Transactional
public void processManyManyEntities() {
    org.hibernate.Sesstion hibernateSession = myDao.getHibernateTemplate().getSessionFactory().getCurrentSession();
    Iterator<Entity> entities = myDao.findEntitesForProcessing();
    while (entities.hasNext()) {
        Entity entity = entities.next();
        hibernateSession.beginTransaction();
        anotherBean.processSingleEntity(entity);
        hibernateSession.getTransaction().commit();
    }
}

processSingleEntity是另一个使用@Transactional注释的bean中的方法,因此所有实体都有一个事务。我检查了什么事务导致异常:它是从hibernateSession.beginTransaction()返回的第一个事务,因此它在事务管理器中没有更新。

有几个问题:

是否可以避免会话绑定异常而不重构dao?这是不相关的问题,因为问题在于Session而hibernate没有用dao

是否可以在事务管理器中更新事务?的解决

是否可以在anotherBean.processSingleEntity(entity);上使用相同的交易(@Transactional)而没有processManyManyEntities注释?

2 个答案:

答案 0 :(得分:1)

我更希望删除&#34; processManyManyEntities()&#34;上的@Transactional注释,并急切加载来自&#34; findEntitesForProcessing&#34;的所有数据。

如果您希望每个数据实体都在&#34; processSingleEntity&#34;中进行交易,那么@Transactinoal on&#34; processSingleEntity&#34;很好。您不必在&#34; processManyManyEntities()&#34;上注释@Transactional。但是在延迟加载的情况下,急切加载是防止源数据加载到另一个会话中的必要手段,例如,在&#34; processSingleEntity&#34;。

由于每个数据实体的事务,源数据加载的事务边界不是您的事务的情况。不要让#懒惰的装载&#34;使您的交易意图复杂化以修改数据。

答案 1 :(得分:1)

可以在事务管理器中更新事务。您需要做的就是从TransactionSynchronizationManager.getResource(sessionFactory)获取SessionHolder实例,并将会话持有者中的事务设置为当前。这使得可以在必要时提交事务,并允许在方法返回后由spring事务管理器提交事务。