Yet Another Robust Way to Listen to Hibernate Events
How to use some of the great new interfaces in Hibernate 4.
We 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.