此版本仍在开发中,尚未被视为稳定版本。如需使用最新的稳定版本,请使用 Spring Data Relational 4.0.4spring-doc.cadn.net.cn

生命周期事件

Spring Data JDBC 会将生命周期事件发布给 ApplicationListener 对象,通常是应用上下文中的 Bean。 事件是对特定生命周期阶段的通知。 与实体回调(entity callbacks)不同,事件旨在用于通知目的。 事务监听器将在事务完成时接收到事件。 事件和回调仅针对聚合根(aggregate roots)触发。 如果您希望处理非根实体,则需要通过其所属聚合根的监听器来实现。spring-doc.cadn.net.cn

实体生命周期事件可能会带来较高的开销,当你加载大型结果集时,可能会注意到性能特征发生变化。 你可以在Template API上禁用生命周期事件。spring-doc.cadn.net.cn

例如,以下监听器会在聚合保存之前被调用:spring-doc.cadn.net.cn

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

    return event -> {

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

如果你只想处理特定领域类型的事件,可以让你的监听器继承 AbstractRelationalEventListener,并重写一个或多个 onXXX 方法,其中 XXX 代表事件类型。 回调方法仅会在与该领域类型及其子类型相关的事件发生时被调用,因此你无需进行额外的类型转换。spring-doc.cadn.net.cn

class PersonLoadListener extends AbstractRelationalEventListener<Person> {

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

下表描述了可用的事件。有关流程步骤之间确切关系的更多详细信息,请参阅可用回调的说明,这些回调与事件一一对应。spring-doc.cadn.net.cn

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

BeforeDeleteEventspring-doc.cadn.net.cn

在聚合根被删除之前。spring-doc.cadn.net.cn

AfterDeleteEventspring-doc.cadn.net.cn

在聚合根被删除之后。spring-doc.cadn.net.cn

BeforeConvertEventspring-doc.cadn.net.cn

在聚合根被转换为执行 SQL 语句的计划之前,但在已确定该聚合是新建的还是已存在的之后,即在决定应执行更新(update)还是插入(insert)操作之后。spring-doc.cadn.net.cn

BeforeSaveEventspring-doc.cadn.net.cn

在聚合根被保存之前(即被插入或更新,但已确定是执行插入还是更新操作之后)。spring-doc.cadn.net.cn

AfterSaveEventspring-doc.cadn.net.cn

在聚合根被保存(即插入或更新)之后。spring-doc.cadn.net.cn

AfterConvertEventspring-doc.cadn.net.cn

在聚合根从数据库 ResultSet 创建完成并设置其所有属性之后。spring-doc.cadn.net.cn

生命周期事件依赖于一个 ApplicationEventMulticaster,在使用 SimpleApplicationEventMulticaster 的情况下,可以配置一个 TaskExecutor,因此无法保证事件处理的具体时机。

特定存储的 EntityCallbacks

Spring Data JDBC 使用 EntityCallback API 提供审计支持,并对下表中列出的回调作出响应。spring-doc.cadn.net.cn

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

删除spring-doc.cadn.net.cn

BeforeDeleteCallbackspring-doc.cadn.net.cn

在实际删除之前。spring-doc.cadn.net.cn

聚合根及其所属聚合中的所有实体都将从数据库中删除。spring-doc.cadn.net.cn

AfterDeleteCallbackspring-doc.cadn.net.cn

聚合被删除之后。spring-doc.cadn.net.cn

保存spring-doc.cadn.net.cn

根据聚合是否为新对象,决定执行插入还是更新操作。spring-doc.cadn.net.cn

BeforeConvertCallbackspring-doc.cadn.net.cn

如果你希望以编程方式设置一个 ID,这是正确的回调方法。在上一步中,新聚合根会被识别出来,而在此步骤中生成的 ID 将用于后续步骤。spring-doc.cadn.net.cn

将聚合对象转换为聚合变更,它是一组要针对数据库执行的 SQL 语句序列。在此步骤中,会判断该聚合是否提供了 ID,或者该 ID 是否仍为空并期望由数据库生成。spring-doc.cadn.net.cn

BeforeSaveCallbackspring-doc.cadn.net.cn

对聚合根所做的更改可能会被考虑,但是否将 ID 值发送到数据库的决定已在上一步中做出。 不要使用此方法为新的聚合创建 ID。请改用 BeforeConvertCallbackspring-doc.cadn.net.cn

上述确定的 SQL 语句将针对数据库执行。spring-doc.cadn.net.cn

AfterSaveCallbackspring-doc.cadn.net.cn

在聚合根被保存(即插入或更新)之后。spring-doc.cadn.net.cn

加载spring-doc.cadn.net.cn

使用一个或多个 SQL 查询加载聚合。从结果集中构造聚合。spring-doc.cadn.net.cn

AfterConvertCallbackspring-doc.cadn.net.cn

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

对于派生查询方法或带注解的查询,不会触发 delete 和 save 相关的回调。 通常情况下,Spring Data JDBC 无法高效地确定哪些聚合根会受到这些操作的影响,因此无法提供回调或事件。spring-doc.cadn.net.cn