エンティティコールバック
Spring Data インフラストラクチャは、特定のメソッドが呼び出される前後にエンティティを変更するためのフックを提供します。いわゆる EntityCallback
インスタンスは、コールバック形式のエンティティをチェックし、潜在的に変更する便利な方法を提供します。
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() の呼び出しサイトから推測されます。 |
次の例に示すように、アプリケーションのニーズに合ったインターフェースを実装します。
BeforeSaveCallback
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
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 | ラムダ式を使用した BeforeSaveCallback 。デフォルトでは順不同で、最後に呼び出されます。ラムダ式によって実装されたコールバックはタイピング情報を公開しないため、割り当て不可能なエンティティでこれらを呼び出すと、コールバックのスループットに影響することに注意してください。class または enum を使用して、コールバック Bean の型フィルタリングを有効にします。 |
4 | 単一の実装クラスに複数のエンティティコールバックインターフェースを組み合わせます。 |