|
此版本仍在开发中,尚未被视为稳定版本。如需最新稳定版本,请使用 Spring Data Cassandra 5.0.4! |
生命周期事件
Cassandra 映射框架内置了多个 org.springframework.context.ApplicationEvent 事件,您的应用程序可以通过在 ApplicationContext 中注册特殊的 Bean 来响应这些事件。
由于这些事件基于 Spring 的应用上下文事件基础设施,因此其他产品(例如 Spring Integration)可以轻松接收这些事件,因为它们是 Spring 应用程序中广为人知的事件机制。
要在对象进入数据库之前拦截它,您可以注册 AbstractCassandraEventListener 的子类并重写 onBeforeSave(…) 方法。
当事件被分发时,您的监听器将被调用并接收域对象(即 Java 实体)。
实体生命周期事件可能开销较大,在加载大型结果集时,您可能会注意到性能特征发生变化。
您可以在 模板 API 上禁用生命周期事件。
以下示例使用了 onBeforeSave 方法:
class BeforeSaveListener extends AbstractCassandraEventListener<Person> {
@Override
public void onBeforeSave(BeforeSaveEvent<Person> event) {
// … change values, delete them, whatever …
}
}
在您的 Spring ApplicationContext 中声明这些 Bean 将导致它们在事件被分发时被调用。
The AbstractCassandraEventListener 具有以下回调方法:
-
onBeforeSave:在CassandraTemplate.insert(…)和.update(…)操作中调用,时机是在数据库中插入或更新行之前,但在创建Statement之后。 -
onAfterSave:在CassandraTemplate…insert(…)和.update(…)操作中,向数据库插入或更新一行数据之后调用。 -
onBeforeDelete:在CassandraTemplate.delete(…)操作中,从数据库删除行之前调用。 -
onAfterDelete:在CassandraTemplate.delete(…)操作中,从数据库删除行之后调用。 -
onAfterLoad:在从数据库中检索每一行数据后,由CassandraTemplate.select(…)、.slice(…)和.stream(…)方法调用。 -
onAfterConvert:在从数据库检索到一行数据并将其转换为 POJO 之后,由CassandraTemplate.select(…)、.slice(…)和.stream(…)方法调用。
| 生命周期事件仅针对根级别类型发出。 作为聚合根内部属性使用的复杂类型不会触发事件发布。 |
实体回调
Spring Data 基础设施提供了在调用某些方法之前和之后修改实体的钩子。
这些所谓的EntityCallback实例提供了一种便捷的方式,以回调风格检查并可能修改实体。
An EntityCallback看起来非常像一个专门的ApplicationListener.
一些 Spring Data 模块会发布特定存储的事件(例如BeforeSaveEvent) 允许修改给定的实体。在某些情况下,例如处理不可变类型时,这些事件可能会引发问题。
此外,事件发布依赖于ApplicationEventMulticaster. 如果使用异步方式配置该功能TaskExecutor它可能导致不可预测的结果,因为事件处理可以分叉到线程上。
实体回调提供了与同步和响应式 API 的集成点,以确保在处理链中定义明确的检查点按顺序执行,并返回一个可能已被修改的实体或响应式包装类型。
实体回调通常按 API 类型进行区分。这种区分意味着同步 API 仅考虑同步实体回调,而响应式实现仅考虑响应式实体回调。
|
实体回调(Entity Callback)API 自 Spring Data Commons 2.2 起引入,是应用实体修改的推荐方式。
现有的特定于存储的 |
实现实体回调
EntityCallback 通过其泛型类型参数直接与其领域类型相关联。
每个 Spring Data 模块通常都提供一组预定义的 EntityCallback 接口,用于覆盖实体的生命周期。
EntityCallback 的结构@FunctionalInterface
public interface BeforeSaveCallback<T> extends EntityCallback<T> {
/**
* Entity callback method invoked before a domain object is saved.
* Can return either the same or a modified instance.
*
* @return the domain object to be persisted.
*/
(1)
T onBeforeSave(T entity, (2)
String collection); (3)
}
| 1 | BeforeSaveCallback 在保存实体之前调用的特定方法。返回一个可能已被修改的实例。 |
| 2 | 持久化之前的实体。 |
| 3 | 一些特定于存储的参数,例如实体所持久化的集合。 |
EntityCallback 的结构@FunctionalInterface
public interface ReactiveBeforeSaveCallback<T> extends EntityCallback<T> {
/**
* Entity callback method invoked on subscription, before a domain object is saved.
* The returned Publisher can emit either the same or a modified instance.
*
* @return Publisher emitting the domain object to be persisted.
*/
(1)
Publisher<T> onBeforeSave(T entity, (2)
String collection); (3)
}
| 1 | BeforeSaveCallback 在订阅时调用的特定方法,在实体保存之前执行。会发出一个可能已被修改的实例。 |
| 2 | 持久化之前的实体。 |
| 3 | 一些特定于存储的参数,例如实体所持久化的集合。 |
可选的实体回调参数由具体的 Spring Data 模块定义,并从 EntityCallback.callback() 的调用点推断得出。 |
实现符合您应用程序需求的接口,如下例所示:
BeforeSaveCallbackclass DefaultingEntityCallback implements BeforeSaveCallback<Person>, Ordered { (2)
@Override
public Object onBeforeSave(Person entity, String collection) { (1)
if(collection == "user") {
return // ...
}
return // ...
}
@Override
public int getOrder() {
return 100; (2)
}
}
| 1 | 根据您的需求实现的回调。 |
| 2 | 如果存在多个针对同一领域类型的实体回调,则可能对其进行排序。排序遵循最低优先级原则。 |
注册实体回调
EntityCallback Bean 会被特定于存储的实现类自动发现,前提是它们已在 ApplicationContext 中注册。
大多数模板 API 已经实现了 ApplicationContextAware,因此能够访问 ApplicationContext。
以下示例说明了一组有效的实体回调注册:
EntityCallback Bean 注册@Order(1) (1)
@Component
class First implements BeforeSaveCallback<Person> {
@Override
public Person onBeforeSave(Person person) {
return // ...
}
}
@Component
class DefaultingEntityCallback implements BeforeSaveCallback<Person>,
Ordered { (2)
@Override
public Object onBeforeSave(Person entity, String collection) {
// ...
}
@Override
public int getOrder() {
return 100; (2)
}
}
@Configuration
public class EntityCallbackConfiguration {
@Bean
BeforeSaveCallback<Person> unorderedLambdaReceiverCallback() { (3)
return (BeforeSaveCallback<Person>) it -> // ...
}
}
@Component
class UserCallbacks implements BeforeConvertCallback<User>,
BeforeSaveCallback<User> { (4)
@Override
public Person onBeforeConvert(User user) {
return // ...
}
@Override
public Person onBeforeSave(User user) {
return // ...
}
}
| 1 | BeforeSaveCallback 从 @Order 注解接收其顺序。 |
| 2 | BeforeSaveCallback 通过实现 Ordered 接口来接收其执行顺序。 |
| 3 | 使用 lambda 表达式实现的 BeforeSaveCallback。默认情况下无序,并在最后被调用。请注意,通过 lambda 表达式实现的回调不会暴露类型信息,因此使用不可赋值的实体调用这些回调会影响回调的吞吐量。请使用 class 或 enum 来为回调 bean 启用类型过滤。 |
| 4 | 在单个实现类中组合多个实体回调接口。 |
特定存储的 EntityCallbacks
Spring Data for Apache Cassandra 使用 EntityCallback API 提供其审计支持,并响应以下回调。
| 回调 | 方法 | 描述 | 订单 |
|---|---|---|---|
|
|
在领域对象被转换为 |
|
|
|
标记一个可审计实体为已创建或已修改 |
100 |
|
|
在保存领域对象之前调用。 |
|