Yet Another Robust Way to Listen to Hibernate Events
How to use some of the great new interfaces in Hibernate 4.
Join the DZone community and get the full member experience.
Join For FreeWe often have a use case where we need to do something extra before or after Hibernate DML operations.
The reason why I am writing this article is because I spent hours trying to figure out the best way to deal with this sort of situation. My problem was that my entities were defined in XML, otherwise I could simply use hibernate annotations like @PreUpdate or @PreInsert to that fun stuff.
Hibernate 4 introduced the following amazing interfaces that made my life simple:
- PostCommitInsertEventListener
- PostCommitUpdateEventListener
- PostCommitDeleteEventListener
Similarly, we have some preEvent listeners:
- PreInsertEventListener
- PreUpdateEventListener
- PreDeleteEventListener
In my use case, I was supposed to provide some extra piece of functionality when entities are inserted, updated, or deleted from the database and the transaction is really committed. If a transaction is rolled back for any reason, I was not interested in doing anything extra.
So this is how I solved the problem.
We simply create a class, something like this that implements the above Post* interfaces:
@Component
public class CRUDEventListener implements PostCommitInsertEventListener, PostCommitUpdateEventListener, PostCommitDeleteEventListener {
@Override
public boolean requiresPostCommitHanding(EntityPersister persister) {
// We must need to return true otherwise we would not be able to receive events
return true;
}
@Override
public void onPostDeleteCommitFailed(PostDeleteEvent event) {
// Here we can do something useful, may be log or notify some external system
}
@Override
public void onPostUpdateCommitFailed(PostUpdateEvent event) {
// Here we can do something useful, may be log or notify some external system
}
@Override
public void onPostInsertCommitFailed(PostInsertEvent event) {
// Here we can do something useful, may be log or notify some external system
}
@Override
public void onPostInsert(PostInsertEvent event) {
if (event.getEntity() instanceof MyEntityInterface) {
// Yeah event.getEntity() yeilds my hibernate entity class
}
}
@Override
public void onPostUpdate(PostUpdateEvent event) {
if (event.getEntity() instanceof MyEntityInterface) {
// Yeah event.getEntity() yeilds my hibernate entity class
}
}
@Override
public void onPostDelete(PostDeleteEvent event) {
if (event.getEntity() instanceof MyEntityInterface) {
// Yeah event.getEntity() yeilds my hibernate entity class
}
}
}
Wait! This is not everything, there is one last mystery that we actually need to register our CRUDEventListener class during startup:
@Component
public class CRUDEventRegistration {
@Autowired
private SessionFactory sessionFactory;
@Autowired
private CRUDEventListener listener;
@PostConstruct
public void registerListeners() {
EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.POST_COMMIT_INSERT).appendListener(listener);
registry.getEventListenerGroup(EventType.POST_COMMIT_UPDATE).appendListener(listener);
registry.getEventListenerGroup(EventType.POST_COMMIT_DELETE).appendListener(listener);
}
}
And boom, it worked like a charm!
Opinions expressed by DZone contributors are their own.
Comments