Hibernate Tips: How to activate an entity listener for all entities
Take your skills to the next level!
The Persistence Hub is the place to be for every Java developer. It gives you access to all my premium video courses, monthly Java Persistence News, monthly coding problems, and regular expert sessions.
Hibernate Tips is a series of posts in which I describe a quick and easy solution for common Hibernate questions. If you have a question for a future Hibernate Tip, please post a comment below.
Question:
We use an EntityListener to write an audit log. Is there an easy way to attach the EntityListener to all entities?
Solution:
In most cases, you register an EntityListener for an entity using the @EntityListeners annotations on an entity class. That works fine if you use different listeners for each entity class.
But it’s inconvenient if you want to assign the same listener to all entity classes. In that situation, it’s easier to use an XML configuration to register the EntityListener to all entities by default.
Configure a default listener
The easiest way to do that is to create a file called orm.xml and place it in the META-INF folder of your jar file. All JPA implementations will read and process that file automatically.
The following code snippet configures the MyEntityListener class as the default EntityListener for all entity classes in the persistence unit.
<entity-mappings> <persistence-unit-metadata> <persistence-unit-defaults> <entity-listeners> <entity-listener class="org.thoughts.on.java.model.MyEntityListener"/> </entity-listeners> </persistence-unit-defaults> </persistence-unit-metadata> </entity-mappings>
A simple EntityListener
The MyEntityListener class is very simple. It only has 1 method that expects an object as a parameter and is annotated with @PreUpdate, @PrePersist, and @PreRemove. Hibernate calls this method and provides then entity object as a parameter whenever it persists, updates or removes an entity for which this listener is registered.
public class MyEntityListener { Logger log = Logger.getLogger(MyEntityListener.class); @PreUpdate @PrePersist @PreRemove public void handleLifecycleEvent(Object entity) { log.info(entity); } }
Use the EntityListener
Let’s give it a try and run this simple test case that persists and updates a Book entity.
EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Book b = new Book(); b.setTitle("Hibernate Tips"); em.persist(b); em.getTransaction().commit(); em.close(); em = emf.createEntityManager(); em.getTransaction().begin(); b = em.find(Book.class, b.getId()); b.setTitle("Hibernate Tips - More than 70 solutions to common Hibernate problems"); em.getTransaction().commit(); em.close();
As you can see in the log file, Hibernate calls the MyEntityListener before the SQL INSERT and the SQL UPDATE statements.
20:03:33,124 INFO [org.thoughts.on.java.model.MyEntityListener] - Book title: Hibernate Tips 20:03:33,127 DEBUG [org.hibernate.SQL] - select nextval ('hibernate_sequence') 20:03:33,160 DEBUG [org.hibernate.SQL] - insert into Book (publishingDate, title, version, id) values (?, ?, ?, ?) 20:03:33,188 DEBUG [org.hibernate.SQL] - select book0_.id as id1_0_0_, book0_.publishingDate as publishi2_0_0_, book0_.title as title3_0_0_, book0_.version as version4_0_0_ from Book book0_ where book0_.id=? 20:03:33,204 INFO [org.thoughts.on.java.model.MyEntityListener] - Book title: Hibernate Tips - More than 70 solutions to common Hibernate problems 20:03:33,205 DEBUG [org.hibernate.SQL] - update Book set publishingDate=?, title=?, version=? where id=? and version=?
Learn more:
If you liked this article, you might also be interested in:
Hibernate Tips Book
Get more recipes like this one in my new book Hibernate Tips: More than 70 solutions to common Hibernate problems.
It gives you more than 70 ready-to-use recipes for topics like basic and advanced mappings, logging, Java 8 support, caching, and statically and dynamically defined queries.