This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Data Relational 3.3.1!

Lifecycle Events

Spring Data JDBC publishes lifecycle events to ApplicationListener objects, typically beans in the application context. Events are notifications about a certain lifecycle phase. In contrast to entity callbacks, events are intended for notification. Transactional listeners will receive events when the transaction completes. Events and callbacks get only triggered for aggregate roots. If you want to process non-root entities, you need to do that through a listener for the containing aggregate root.

Entity lifecycle events can be costly, and you may notice a change in the performance profile when loading large result sets. You can disable lifecycle events on the Template API.

For example, the following listener gets invoked before an aggregate gets saved:

@Bean
ApplicationListener<BeforeSaveEvent<Object>> loggingSaves() {

	return event -> {

		Object entity = event.getEntity();
		LOG.info("{} is getting saved.", entity);
	};
}

If you want to handle events only for a specific domain type you may derive your listener from AbstractRelationalEventListener and overwrite one or more of the onXXX methods, where XXX stands for an event type. Callback methods will only get invoked for events related to the domain type and their subtypes, therefore you don’t require further casting.

class PersonLoadListener extends AbstractRelationalEventListener<Person> {

	@Override
	protected void onAfterLoad(AfterLoadEvent<Person> personLoad) {
		LOG.info(personLoad.getEntity());
	}
}

The following table describes the available events.For more details about the exact relation between process steps see the description of available callbacks which map 1:1 to events.

Table 1. Available events
Event When It Is Published

BeforeDeleteEvent

Before an aggregate root gets deleted.

AfterDeleteEvent

After an aggregate root gets deleted.

BeforeConvertEvent

Before an aggregate root gets converted into a plan for executing SQL statements, but after the decision was made if the aggregate is new or not, i.e. if an update or an insert is in order.

BeforeSaveEvent

Before an aggregate root gets saved (that is, inserted or updated but after the decision about whether if it gets inserted or updated was made).

AfterSaveEvent

After an aggregate root gets saved (that is, inserted or updated).

AfterConvertEvent

After an aggregate root gets created from a database ResultSet and all its properties get set.

Lifecycle events depend on an ApplicationEventMulticaster, which in case of the SimpleApplicationEventMulticaster can be configured with a TaskExecutor, and therefore gives no guarantees when an Event is processed.

Store-specific EntityCallbacks

Spring Data JDBC uses the EntityCallback API for its auditing support and reacts on the callbacks listed in the following table.

Table 2. Process Steps and Callbacks of the Different Processes performed by Spring Data JDBC.
Process EntityCallback / Process Step Comment

Delete

BeforeDeleteCallback

Before the actual deletion.

The aggregate root and all the entities of that aggregate get removed from the database.

AfterDeleteCallback

After an aggregate gets deleted.

Save

Determine if an insert or an update of the aggregate is to be performed dependen on if it is new or not.

BeforeConvertCallback

This is the correct callback if you want to set an id programmatically. In the previous step new aggregates got detected as such and a Id generated in this step would be used in the following step.

Convert the aggregate to a aggregate change, it is a sequence of SQL statements to be executed against the database. In this step the decision is made if an Id is provided by the aggregate or if the Id is still empty and is expected to be generated by the database.

BeforeSaveCallback

Changes made to the aggregate root may get considered, but the decision if an id value will be sent to the database is already made in the previous step. Do not use this for creating Ids for new aggregates. Use BeforeConvertCallback instead.

The SQL statements determined above get executed against the database.

AfterSaveCallback

After an aggregate root gets saved (that is, inserted or updated).

Load

Load the aggregate using 1 or more SQL queries. Construct the aggregate from the resultset.

AfterConvertCallback

We encourage the use of callbacks over events since they support the use of immutable classes and therefore are more powerful and versatile than events.