📜 ⬆️ ⬇️

Spring and event handling in Hibernate

Somehow deprived on Habré such a topic as event handling when working with entities using Hibernate - I could find only one post for almost a shaggy year. But that audit, and we need the ability to automate work with some attributes of entities and at the same time simplify the procedure for working with them.

To begin with, we will create a demo stand with two User entities and AnObject, as well as a DAO layer for them.
Code
Hereinafter I cite only significant pieces of code - in the full version you can look at github
@Entity @Table(name = "user") public class User { @Id @GeneratedValue private long id; @Basic @Column(name = "username", updatable = false, unique = true, nullable = false) private String username; // getter and setter } 

 @Entity @Table(name = "anObject") public class AnObject { @Id @GeneratedValue private long id; @Column private String value; // getter and setter } 



Add an attribute with two properties to the AnObject entity - the last edit date and the author of the edit:
Code
 @Embeddable public class LastModified { @Column @Temporal(TemporalType.TIMESTAMP) private Calendar lastUpdated; @OneToOne @JoinColumn(name = "lastEditor_id") private User lastEditor; // getter and setter } 

 public interface LastModifiable { LastModified getLastModified(); void setLastModified(LastModified modified); } 

 @Entity @Table(name = "anObject") public class AnObject implements LastModifiable { @Id @GeneratedValue private long id; @Column private String value; @Embedded private LastModified lastModified; // getter and setter } 


And do not forget to fix the test class , taking into account innovations.

From this point on, we already have everything we need to make data about the date / author of changes in manual mode, but ... we are “lazy” people, so let's automate this work - let Hibernate do it for us everywhere. To do this, add a Listener and ask Hibernate to use it when a save or update ( commit ) event occurs:
Code
 @Component public class LastModifiedListener extends DefaultSaveOrUpdateEventListener { private transient static final Logger LOG = LoggerFactory.getLogger(LastModifiedListener.class.getName()); @Autowired private UserDao userDao; @Override public void onSaveOrUpdate(SaveOrUpdateEvent event) { LOG.trace("object: {}", event.getObject()); if (event.getObject() instanceof LastModifiable) { LastModified lastModified = new LastModified((User) userDao.get(2)); ((LastModifiable) event.getObject()).setLastModified(lastModified); LOG.trace("object: {}", event.getObject()); } super.onSaveOrUpdate(event); } } 

 @Component public class HibernateEventWiring { @Autowired private SessionFactory sessionFactory; @Autowired private LastModifiedListener lastModifiedListener; @PostConstruct public void registerListeners() { EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService( EventListenerRegistry.class); registry.getEventListenerGroup(EventType.SAVE_UPDATE).prependListener(lastModifiedListener); } } 


')
Now there is a final touch - to correct the tests so that they take into account the new changes (although it would be better to correct the tests first, and then add the Listener)

At this point, you can put a final point - for any entity that implements the LastModifiable interface automatically each time it is saved in the database, the lastUpdated and lastEditor fields will change.

UPD: In the example there was a slight understatement - the audition was only for the saveOrUpdate event, while it can be called and just save and just update. updated tests
UPD: Updated sources - added an example using Spring Data JPA (used only entities, without listeners). The listener org.springframework.data.jpa.domain.support.AuditingEntityListener did not add to save the example with event handling in Hibernate

Source: https://habr.com/ru/post/204854/


All Articles