我使用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
注释?
答案 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事务管理器提交事务。