Back to Home

Spring and event handling in Hibernate

spring framework · hibernate · testng · programming · java · examples · listeners

Spring and event handling in Hibernate

  • Tutorial
Such topic as event handling when working with entities using Hibernate was somehow deprived on the hub - I could find only one post for almost a furry year. But it’s an audit, but we need the ability to automate the work with some attributes of entities and at the same time simplify the procedure for working with them.

First, create a demo stand with two User and AnObject entities, as well as a DAO layer for them.
The code
Hereinafter I bring only significant pieces of code - in the full version you can see on 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 date of the last editing and the author of the edit:
The 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 with the innovations.

From now on, we already have everything we need to make data on the date / author of the 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 the save or update ( commit ) event occurs :
The 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 the final touch remains - to correct the tests so that they take into account new changes (although it would be more correct to correct the tests first, and then add the Listener)

This can be the final point - for any entity that implements the LastModifiable interface automatically every time it is saved to the database lastUpdated and lastEditor fields will be changed.

UPD: In the example there was a slight understatement - listening was only for the saveOrUpdate event, while just save and just update could be called. updated
UPD tests : Updated source - added an example using Spring Data JPA (used only entities, without listeners). Listenerorg.springframework.data.jpa.domain.support.AuditingEntityListener I didn’t add to keep the example with event handling in Hibernate

Read Next