@Transactional attribute is manually captured

I am using spring + hibernate pattern to handle objects. There are quite a few objects to load at once, so I get the iterator from the hibernate template.

Each object must be treated as a whole. I tried to put the processing of the object in a separate transaction (propagation = REQUIRED_NEW). However, I ended up throwing an exception by stating that the proxy is limited to two sessions. This is due to a suspended transaction used for iterative lazy loading. I am using the same bean for lazy loading and object handling. (Maybe it should be refactored into two separate Taoists, one for lazy loading and one for processing?)

Then I tried to use a single transaction that was committed after each object was processed. Much better here, there are no exceptions during entity processing, but after processing is complete and the method returns, an exception is thrown from spring transaction management code.

@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

is a method in another bean, annotated with @Transactional

, so there is one transaction for all objects. I checked which transaction is throwing the exception: this is the first transaction returned from hibernateSession.beginTransaction()

, so it just doesn't update in the transaction manager.

There are several questions:

is it possible to exclude the binding exception without refactoring the dao? which is not a relevant question as the problem is with session and sleeping not with dao

Can I update a transaction in the Transaction Manager? solved

Can I use the same transaction (for anotherBean.processSingleEntity(entity);

) without annotation @Transactional

on processManyManyEntities

?

+3


source to share


2 answers


It is possible to update the transaction in the transaction manager. All you have to do is get a SessionHolder instance from TransactionSynchronizationManager.getResource(sessionFactory)

and set the transaction in the session holder to the current one. This allows transactions to be committed whenever needed and allows transactions to be committed by the spring transaction manager after the method returns.



+1


source


I would rather remove the @Transactional annotation on "processManyManyEntities ()" and to eagerly load all data from "findEntitesForProcessing".

If you want each data entity to be transactional on "processSingleEntity", @Transactinoal on "processSingleEntity" is fine. You don't need to comment @Transactional on "processManyManyEntities ()". But in the case of lazy loading, eager loading is a necessary means to prevent the raw data from loading into another session, say in "processSingleEntity".



Since there is a transaction for every data object, the transaction boundary when loading the original data is not relevant to your transaction. Don't let lazy loading complicate your transaction target for data modification.

+1


source







All Articles