How to save new Entity inside Hibernate Listeners

Most of times the simple and effective way to create auditing for Hibernate entities is envers framework.

But sometimes you wish to control the audited entity and create the Pojo explicit in your code and not be dependent with the implementation of envers.

For example you have general entities' filtering mechanism which has to receive an entity. I didn't find any way to retrieve the envers audited entity.

In this case you can use Hibernatre Listeners to achieve the same concept.

The idea is to create the audited entity for each action like: insert, update & delete.

Saving the new audited entity is pretty simple for PostUpdateListener & PostDeleteListener:

public class PostUpdateListener implements org.hibernate.event.PostUpdateEventListener {
        @Override
        public void onPostUpdate(PostUpdateEvent event) {
                AuditedEntity auditedEntity = new AuditedEntity(...);
                event.getSession().save(auditedEntity);
        }
}

But saving a new entity for PostInsertListener is more complicated. The reason is you cannot use the same Hibernate session for saving a new entity in the middle of saving the original entity.

The solution I use to overcome this issue was to create another session factory and save the audited entity with the new session factory:

public class PostInsertListener implements org.hibernate.event.PostInsertEventListener {
        private SessionFactory sessionFactory;

        public void setSessionFactory(SessionFactory sessionFactory) {
                this.sessionFactory = sessionFactory;
        }
        @Override
        public void onPostInsert(PostInsertEvent event) {
                AuditedEntity auditedEntity = new AuditedEntity(...);
                saveNewEntityFromWithinEventListener(auditedEntity);
        }
        private void saveNewEntityFromWithinEventListener(Object newEntity) {
                sessionFactory.getCurrentSession().save(newEntity);
        }
}

Pay attention to create your audited entity in a different package and set it to the new session factory package to scan property. This way the session factory maps only the audited entity it used.

I'm sure there are more methods to overcome this issue with Hibernate insert listener, and it will be great you share them with us in your comments.