Reputation: 745
I am currently working with @PostPersist
and @PostUpdate
, and in those triggers I am persisting additional entities. The question is, are those triggers in the same transaction and if not is it possible to force it ?
For me it works this way.
While I was looking through the logs the transaction isn't existing ( it's commited just before the trigger is launched ) which prevents me ( without REQUIRES_NEW
on the persisting method from injected bean ) from saving the additional entities in database.
REQUIRED
attribute is totally ignored, and MANDATORY
attribute do not throw an exception.
Can it be the problem with JUnit ( since I am in the dev. phase and did not test the behavior on full env. ) ?
If extending the transaction on this triggers is not possible, how to ensure that if the rollback occurs before the @PostPersist
and @PostUpdate
, those operations also will be rollbacked.
Upvotes: 21
Views: 31476
Reputation: 10549
If you're using Spring you could always register a TransactionSynchronization
with your current transaction manager to be called back on events such as commits of your currently running transaction:
@PostPersist
void onPersist() {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void beforeCommit(boolean readOnly) {
// do work
}
});
}
}
A TransactionSynchronization
also provides callbacks after a transaction has committed successfully and before/after a transaction completes.
If you need to inspect if the transaction was committed or rolled back, use afterCompletion(int status)
.
For details have a look at TransactionSynchronization's JavaDoc.
Upvotes: 29
Reputation: 2051
The firing of a PostPersist event does not indicate that the entity has done a successful commit. The transaction may be rolled back after the firing of the event but before the successful commit. If you in the PostPersist get the entity manager used in the transaction and then do somehting like this:
@PostPersist
void someMethod() {
EntityManager em = null;
em = getEntityManagerUsedInTransaction();
EntityTransaction et = em.getTransaction(); // should return the current transaction
if (et.isActive() ) {
// do more db stuff
}
}
NB: I haven't tried this so it's only speculation (tho' I have used the lifetime event trigger extensively for other stuff). I have to add that I don't think this is a good idea. Use the PostPersist to flag that other entities should be persisted and do it in another transaction.
Upvotes: 13