生命周期事件

Spring Data JDBC 将生命周期事件发布到 ApplicationListener 对象,这些对象通常是应用上下文中的 bean。事件是关于特定生命周期阶段的通知。与实体回调不同,事件旨在用于通知。事务性监听器将在事务完成时接收事件。事件和回调仅对聚合根触发。如果您想处理非根实体,需要通过包含该非根实体的聚合根的监听器来处理。

实体生命周期事件可能开销很大,加载大型结果集时,您可能会注意到性能特征发生变化。您可以通过 模板 API 禁用生命周期事件。

例如,以下监听器在聚合保存之前被调用

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

	return event -> {

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

如果您只想处理特定领域类型的事件,可以将监听器派生自 AbstractRelationalEventListener 并覆盖一个或多个 onXXX 方法,其中 XXX 代表事件类型。回调方法仅对与该领域类型及其子类型相关的事件调用,因此您无需进行额外的类型转换。

class PersonLoadListener extends AbstractRelationalEventListener<Person> {

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

下表描述了可用的事件。有关处理步骤之间确切关系的更多详细信息,请参阅与事件一对一映射的可用回调描述

表 1. 可用事件
事件 何时发布

BeforeDeleteEvent

在聚合根被删除之前。

AfterDeleteEvent

在聚合根被删除之后。

BeforeConvertEvent

在聚合根被转换为执行 SQL 语句的计划之前,但在决定聚合是否是新的(即是更新还是插入)之后。

BeforeSaveEvent

在聚合根被保存之前(即插入或更新,但在决定是插入还是更新之后)。

AfterSaveEvent

在聚合根被保存之后(即插入或更新)。

AfterConvertEvent

在从数据库 ResultSet 创建聚合根并设置所有属性之后。

生命周期事件依赖于 ApplicationEventMulticaster,对于 SimpleApplicationEventMulticaster 来说,它可以配置一个 TaskExecutor,因此无法保证事件何时被处理。

特定于存储的实体回调

Spring Data JDBC 使用 EntityCallback API 进行审计支持,并对下表中列出的回调做出反应。

表 2. Spring Data JDBC 执行的不同过程的处理步骤和回调。
过程 EntityCallback / 处理步骤 注释

删除

BeforeDeleteCallback

实际删除之前。

聚合根及其所有实体都将从数据库中移除。

AfterDeleteCallback

聚合被删除之后。

保存

根据聚合是否是新的来决定是执行插入还是更新操作。

BeforeConvertCallback

如果您想以编程方式设置 ID,这是正确的回调。在上一步中,新的聚合已被检测出来,在此步骤中生成的 ID 将会在下一步中使用。

将聚合转换为聚合更改,这是一系列将要对数据库执行的 SQL 语句。在此步骤中,决定 ID 是由聚合提供,还是 ID 仍然为空并期望由数据库生成。

BeforeSaveCallback

对聚合根的更改可能会被考虑,但是否将 ID 值发送到数据库的决定已在上一步中做出。不要使用此回调为新聚合创建 ID。请改用 BeforeConvertCallback

上面确定的 SQL 语句将对数据库执行。

AfterSaveCallback

在聚合根被保存之后(即插入或更新)。

加载

使用一个或多个 SQL 查询加载聚合。从结果集中构建聚合。

AfterConvertCallback

我们鼓励使用回调而非事件,因为回调支持使用不可变类,因此比事件更强大、更灵活。