その段落が言うように、標準はエンティティ リスナー内からのエンティティ マネージャ メソッドの呼び出しをサポートしていません。Heiko Rupp が回答で述べているように、永続化されたエンティティから構築することを強くお勧めします。custData
それが不可能な場合は、次のことを検討してください。
- 非同期に通知します。おそらく適切に動作するタイミングに依存するため、これはあまりお勧めしません。
パブリッククラスEntityListener {
private final static String QUEUE_NAME = "顧客";
プライベート ScheduledExecutorService getExecutorService() {
// どこかから非同期エグゼキュータ サービスを取得します
// ほとんどの場合、ScheduledExecutorService が必要になります
// インスタンス、通知をスケジュールするために
// 若干の遅延。または、 Thread.sleep(...) を試すこともできます
// 通知する前ですが、それは醜いです。
}
private void doNotifyOtherInNewTransaction(顧客エンティティ) {
// これらすべてが正しく機能するには、
// 通知を実行する必要があります
// 新しいトランザクション内。あなたかもしれません
// これは宣言的に行う方が簡単です
// 区切られたメソッドを呼び出すことによって
// REQUIRES_NEW 付き
試す {
// (トランザクションを開始)
doNotifyOther(エンティティ);
// (トランザクションをコミット)
} catch (例外例) {
// (ロールバック トランザクション)
}
}
@PostUpdate
@PostPersist
public void notifyOther(最終的な顧客エンティティ) {
ScheduledExecutorService エグゼキュータ = getExecutorService();
// これは「未加工」バージョンです
// ほとんどの場合、呼び出す必要があります
// executor.schedule で遅延を指定し、
// 古いトランザクションに時間を与えるために
// フラッシュしてコミットする
executor.execute(新しいRunnable() {
@オーバーライド
public void run() {
doNotifyOtherInNewTransaction(エンティティ);
}
});
}
// これは元のコードとまったく同じです
public void doNotifyOther(顧客エンティティ) {
CustomerFacadeREST custFacade = new CustomerFacadeREST();
Integer customerId = entity.getCustomerId();
文字列 custData = custFacade.find(customerId).toString();
String successMessage = "エンティティがサーバーに追加されました";
試す {
ConnectionFactory factory = 新しい ConnectionFactory();
factory.setHost("localhost");
接続 connection = factory.newConnection();
チャンネル channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicPublish("", QUEUE_NAME, null, custData.getBytes());
channel.close();
connection.close();
}
キャッチ(IOExceptionの例){
}
最後に {
}
}
}
- コミット後のトリガーを登録します(Heilo Ruppの回答が実行できない場合の私の推奨事項)。これは、データベースにフラッシュした後に実行されることが保証されているため、タイミングに依存しません。さらに、トランザクションをロールバックしても通知されないという追加の利点があります。これを行う方法は、トランザクション管理に何を使用しているかによって異なりますが、基本的には特定のインスタンスのインスタンスを作成し、それをレジストリに登録します。たとえば、JTA では次のようになります。
パブリッククラスEntityListener {
private final static String QUEUE_NAME = "顧客";
プライベート トランザクション getTransaction() {
// どこかから現在の JTA トランザクション参照を取得します
}
private void doNotifyOtherInNewTransaction(顧客エンティティ) {
// これらすべてが正しく機能するには、
// 通知を実行する必要があります
// 新しいトランザクション内。あなたかもしれません
// これは宣言的に行う方が簡単です
// 区切られたメソッドを呼び出すことによって
// REQUIRES_NEW 付き
試す {
// (トランザクションを開始)
doNotifyOther(エンティティ);
// (トランザクションをコミット)
} catch (例外例) {
// (ロールバック トランザクション)
}
}
@PostUpdate
@PostPersist
public void notifyOther(最終的な顧客エンティティ) {
トランザクション transaction = getTransaction();
transaction.registerSynchronization(新しい同期() {
@オーバーライド
public void beforeCompletion() { }
@オーバーライド
public void afterCompletion(int ステータス) {
if (ステータス == Status.STATUS_COMMITTED) {
doNotifyOtherInNewTransaction(エンティティ);
}
}
});
}
// これは元のコードとまったく同じです
public void doNotifyOther(顧客エンティティ) {
CustomerFacadeREST custFacade = new CustomerFacadeREST();
Integer customerId = entity.getCustomerId();
文字列 custData = custFacade.find(customerId).toString();
String successMessage = "エンティティがサーバーに追加されました";
試す {
ConnectionFactory factory = 新しい ConnectionFactory();
factory.setHost("localhost");
接続 connection = factory.newConnection();
チャンネル channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicPublish("", QUEUE_NAME, null, custData.getBytes());
channel.close();
connection.close();
}
キャッチ(IOExceptionの例){
}
最後に {
}
}
}
Spring トランザクションを使用している場合、コードは非常に似ていますが、クラス名がいくつか変更されています。
いくつかのポインタ: