Spring and event handling in Hibernate
- Tutorial
First, create a demo stand with two User and AnObject entities, as well as a DAO layer for them.
@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:
@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 :
@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). Listener
org.springframework.data.jpa.domain.support.AuditingEntityListener I didn’t add to keep the example with event handling in Hibernate