Spring Data访问Elasticsearch----实体回调Entity Callbacks

Spring Data访问Elasticsearch----实体回调Entity Callbacks

Spring Data基础结构提供了钩子,用于在调用某些方法之前和之后修改实体。这些所谓的EntityCallback实例提供了一种方便的方式来检查并可能以回调风格修改实体。
EntityCallback看起来很像一个专门的ApplicationListener。一些Spring Data模块发布特定于存储的事件(如BeforeSaveEvent),允许修改给定的实体。在某些情况下,例如在处理不可变类型时,这些事件可能会造成麻烦。此外,事件发布依赖于ApplicationEventMulticaster。如果使用异步TaskExecutor进行配置,可能会导致不可预测的结果,因为事件处理可能会分叉到线程上。
实体回调为同步API和反应式(reactive)API提供了集成点,以保证在处理链中定义良好的检查点(checkpoints)按顺序执行,从而返回可能修改的实体或反应式包装器类型。
实体回调通常由API类型分隔。这种分离意味着同步API只考虑同步实体回调,而反应式实现只考虑反应式实体回调。
实体回调API是在Spring Data Commons 2.2中引入的。这是应用实体修改的推荐方式。在调用可能注册的EntityCallback实例之前,仍会发布现有的特定于存储的ApplicationEvents。

一、实现实体回调

EntityCallback通过其泛型类型参数与其域类型直接关联。每个Spring Data模块通常附带一组覆盖实体生命周期的预定义EntityCallback接口。
EntityCallback的剖析

java 复制代码
@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剖析

java 复制代码
@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. 在保存实体之前,在subscription上调用BeforeSaveCallback特定的方法。发出一个可能已修改的实例。
2. 就在持久化之前的实体。
3. 许多特定于存储的参数,如实体持久化到的集合。

可选的实体回调参数由实现的Spring Data模块定义,并从EntityCallback.callback()的调用位置推断。

实现适合您的应用程序需求的接口,如下面的示例所示:
示例BeforeSaveCallback

java 复制代码
class 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 beans在ApplicationContext中注册,则由特定于存储的实现拾取。大多数template API已经实现ApplicationContextAware,因此可以访问ApplicationContext

以下示例解释了有效实体回调注册的集合:
EntityCallback Bean注册示例

java 复制代码
@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. BeforeSaveCallback使用lambda表达式。默认情况下未排序,最后调用。请注意,由lambda表达式实现的回调不会公开类型信息,因此使用不可分配的实体调用这些信息会影响回调吞吐量。使用类或枚举为回调bean启用类型筛选。
4. 在一个实现类中组合多个实体回调接口。

三、存储特定的EntityCallbacks

Spring Data Elasticsearch在内部使用EntityCallback API来支持其auditing,并对以下回调做出反应:
表1:支持的实体回调

Callback Method Description Order
Reactive/BeforeConvertCallback onBeforeConvert(T entity, IndexCoordinates index) 在域对象转换为org.springframework.data.elasticsearch.core.document.Document之前调用。可以返回实体或修改后的实体,然后将其转换。 Ordered.LOWEST_PRECEDENCE
Reactive/AfterLoadCallback onAfterLoad(Document document, Class type, IndexCoordinates indexCoordinates) 在从Elasticsearch得到的结果被读入org.springframework.data.elasticsearch.core.document.Document之后调用。 Ordered.LOWEST_PRECEDENCE
Reactive/AfterConvertCallback onAfterConvert(T entity, Document document, IndexCoordinates indexCoordinates) 在从Elasticsearch读取结果数据时,从"org.springframework.data.aelasticsearch.core.document.document"转换为域对象后调用。 Ordered.LOWEST_PRECEDENCE
Reactive/AuditingEntityCallback onBeforeConvert(Object entity, IndexCoordinates index) 标记创建或修改的可审核实体 100
Reactive/AfterSaveCallback T onAfterSave(T entity, IndexCoordinates index) 在保存域对象后调用。 Ordered.LOWEST_PRECEDENCE
相关推荐
helloworld_工程师1 分钟前
Spring AI应用:利用DeepSeek+嵌入模型+Milvus向量数据库实现检索增强生成--RAG应用(超详细)
java·后端
顾林海11 分钟前
深度解析TreeSet工作原理
android·java·面试
八股文领域大手子14 分钟前
《从 MyBatis-Plus 到 Elasticsearch:一个后端的性能优化踩坑实录》
elasticsearch·性能优化·mybatis
花木凋零成兰23 分钟前
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接
java·安全·ssl
CXH72828 分钟前
Git 的进阶功能和技巧
大数据·elasticsearch·搜索引擎
振鹏Dong28 分钟前
剖析Spring中的设计模式(一) | 工厂&观察者
java·spring·设计模式
LUCIAZZZ28 分钟前
总结一下常见的EasyExcel面试题
java·spring·操作系统·springboot·poi·easyexcel
猿java30 分钟前
为什么说缓存是把双刃剑?
java·后端·面试
绿柱石38 分钟前
华为ar1200修改con口密码
java·华为·ffmpeg
得物技术42 分钟前
DPP推荐引擎架构升级演进之路|得物技术
java·算法·ab测试