生命周期事件

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 配置,因此不保证何时处理事件。

特定于存储的 EntityCallbacks

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

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