views:

155

answers:

4

I have this code:

run big query: Select all unprocessed objects from table A
for each result
    create or update an output object in table B
    update input object: Set it to "processed"

I'd like to have a transaction over the loop body, that is after one row of input is processed, the updated objects should be committed, so when the program aborts, it won't process all rows again but start with the faulty row.

I'm using Spring 2.5, Hibernate 3.4 and JPA (i.e. I have an EntityManager).

How do I do that? I tried to call em.getTransaction().commit() in the loop but Spring won't allow that.

A: 

Hi,

You should work with the Hibernate's Session object.

Having an javax.persistence.EntityManager instance (I suppose "em"):

((org.hibernate.Session) em.getDelegate()).beginTransaction();

More info: https://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html

ATorras
A: 

Without looking up the spring docs and not knowing your transaction setup:

First you have to setup a transaction manager (probably HibernateTransactionManager). Then IMHO it's best to use Spring's TransactionTemplate to run each iteration inside it's own transaction. You have to make sure, that either the TransactionTemplate really starts a new transaction or no transaction is running on entering the method.

One tip: use the transaction manager's class name as the log category for debugging transaction behavior.

rudolfson
+1  A: 

The entity manager read operations do not require a transaction. So I would trying refactoring out an internal method to update the row and set it to transactional. Note that it will need to be a public method to use @transactional.

James McMahon
+1  A: 

I would recommend looking at spring's TransactionTemplate. The TransactionTemplate documentation contains examples which address exactly what you are trying to achieve.

Rich Kroll