Skip to content
/ dachs Public

Dachs - Data Change Snitch - Unified persistence events


Notifications You must be signed in to change notification settings


Repository files navigation

Dachs - Data Change Snitch

Build Status Maven Central Codacy Badge

A unified entity change-listener across different persistence APIs and implementations.


In almost all back-end systems there is the need to notify or update additional data whenever core data changes. It can be sending a notification event, invalidating cache entries, audit logging or updating a search index to mention a few.

For example Spring has already support for events, and from Spring 4.2 it also has support for send-at-end-of-transaction-events. Further Spring JPA supports auditing, however it does not support fetching the actual data, just who changed it and when. There is no recollection of what was changed.

Dachs flow

All the different persistence frameworks have their different APIs for detecting data changes. With Dachs you have one simple, unified API to deal with.

Maven artifact


Supported persistence frameworks


The goal is to have a simple, but powerful API to get notifications of all changes to entities, that is created, updated and deleted.

Transactional listener

This listener will buffer all events until the transaction is about to commit. preDataChanged is called just before the transaction is committed. Any exception here will abort the transaction. postDataChanged is called just after the transaction is committed.

public interface EntityChangeSetListener
  void preDataChanged(EntityDataChangeSet changeset);
  void postDataChanged(EntityDataChangeSet changeset);

Both methods gives you an EntityDataChangeSet whichs holds all operations performed inside the transaction.

public interface EntityDataChangeSet
  List<EntityDataChange> getCreated();
  List<EntityDataChange> getUpdated();
  List<EntityDataChange> getDeleted();
  boolean isEmpty();
Non-transactional listener


public interface EntityChangeListener
  void preCreate(EntityDataChange entityData);
  void preUpdate(EntityDataChange entityData);
  void preDelete(EntityDataChange entityData);
  void created(EntityDataChange entityData);
  void updated(EntityDataChange entityData);
  void deleted(EntityDataChange entityData);

Using this simple listener, we get an EntityDataChange object for each operation on the entity.

Common for both trasactional and non-transactional
public interface EntityDataChange
  Serializable getId();
  Object getEntity();
  List<PropertyChange<?>> getPropertyChanges();
  Optional<PropertyChange<?>> getPropertyChange(String propertyName);

Each EntityDataChange object holds a collection of PropertyChanges that is the individual properties that has changed.

public interface PropertyChange<T>
  String getPropertyName();
  Class<T> getPropertyType();
  T getOldValue();
  T getNewValue();

Example output

Given a simple Person object:

public class Person()
  private String name;
  private Integer age;
    * name - null => "John Doe"
    * age - null => 34
    * name - "John Doe" => "John Smith"
    * age - 34 => 47
    * name - "John Smith" => null
    * age - 47 => null


Dachs relies on the persistence framework in use to notify about operations and there might be limitations. In general bulk delete will not trigger delete events (aka DELETE FROM Entity).