Reputation: 393
I'm inserting/updating 3 tables while using manual transaction. I want to insert into an history table right after the transaction was committed. that means that there were 3 em.persist
actions (for each table), and only after committing them I would like to call a method.
This is my code:
@Resource
private EJBContext context;
public void save(Object obj)
{
try
{
transaction = context.getUserTransaction();
transaction.begin();
em.persist(obj);
sb2.save(obj); //persist in sb2
sb3.save(obj); //persist in sb2
transaction.commit();
}
catch (Exception exp)
{
transaction.rollback();
}
}
Is there any kind of post commit method? How can I call a method after the commit, and not after the persist?
Upvotes: 7
Views: 6740
Reputation: 1571
If you are in a JPA 2.2 + CDI + JTA environment, you could leverage CDI events which can be observed at a specified transaction phase.
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface EntityEvent {}
public class MyListener {
@Inject
@EntityEvent
private Event<Object> event;
@PostUpdate
public void postUpdate(Object entity) {
event.fire(entity);
}
}
public class MyObserver {
public void afterCommit(@Observes(during = TransactionPhase.AFTER_SUCCESS) @EntityEvent Object entity) {
// do something...
}
}
@EntityListeners(MyListener.class)
public class MyEntity {}
Upvotes: 2
Reputation: 1571
You could use TransactionSynchronizationRegistry
to register a callback to be executed after the transaction completes:
public class MyListener {
// if you can't inject it with @Resource, you'll have to fetch it from JNDI
@Resource
private javax.transaction.TransactionSynchronizationRegistry registry;
@PostUpdate
public void postUpdate(final Object entity) {
registry.registerInterposedSynchronization(new Synchronization() {
public void beforeCompletion() {}
public void afterCompletion(int status) {
if (status == javax.transaction.Status.STATUS_COMMITTED) {
// Do something with your entity
}
}
});
}
}
Then annotate your entities with @EntityListeners(MyListener.class)
(or add it in your orm.xml
).
Upvotes: 6
Reputation: 18379
JPA does not provide such events, but EclipseLink provides extended events through the SessionEventListener API.
http://eclipse.org/eclipselink/documentation/2.5/jpa/extensions/p_session_event_listener.htm
You could also consider the container JTA events.
Upvotes: 0