I'm using Spring's transaction support and JPA (Hibernate) to persist my entities. Everything's working as it should, but I'm stuck when dealing with partial updates within one request:
For every user (HTTP) request I've to write a log entry into a database table, even if an update of the "main" business entity fails (for instance because of a validation error). So my first/principal transaction get's rolled back, but the second (writing the log) should commit. This seems to work using the correct propagation level for writing the log entry:
@Repository
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class UserTracker extends ... {
@PersistenceContext private EntityManager em;
public void log(...) {
// create log entity and persist it
...
em.persist(log);
em.flush();
}
}
My problem is, however, that I get the same EntityManager injected in the second transaction as in the first. So flushing the entity manager (either explicitly or implicitly when the second transaction commits) will also flush my dirty business entity from the first transaction.
How can I remedy this? I would like to use a second, clean and fresh EntityManager for the logging part and I know I could open one programmatically, but is there a cleaner/declarative "Spring-way" of doing this?
EDIT:
My problem might stem from the fact, that my second transaction was nested within my main business transaction:
|-------------- A --------------X <- Rollback of main business transaction (A)
|--- B ---| <- Commit of second log transaction (B)
I've solved my issue serializing the two transactions:
|--------- A --------X |--- B ---|
So everything's good now, but just out of curiosity: If I would stick to my first approach and not resort to JDBC as suggested: How would I configure the entity manager for the second (nested) transaction, so that I get a fresh one for the new transaction. Can this be done?