1

教義モデルにセキュリティ層を追加したいと考えています。SQL レベルでドクトリン フィルター内にアクセス許可チェックを追加できるようにするには、エンティティごとに計算されたアクセス制御トークンのキャッシュを含むいくつかのデータベース テーブルを維持する必要があります。

ここで、これらのテーブルを更新する必要があり、場合によっては、これらのキャッシュ テーブルの 1 つを完全に再構築する必要があります。これは、onFlush イベントをリッスンするイベント リスナーで行う必要があります。これをアーカイブするための最良の (最もパフォーマンスと信頼性の高い) 方法は何でしょうか?

新しいエンティティを永続化する方法と、既に永続化されているエンティティの関連付けとプリミティブ プロパティを変更する方法が文書化されています。これは、作業単位オブジェクトの computeChangeSet() または recomputeSingleEntityChangeSet() を呼び出し、各エンティティをこれらのメソッドのいずれかに渡すことによって行われます。これらの更新中はシステム全体をロックする必要があり、めったにありませんが、できるだけ早く実行する必要があります。また、最初にすべてのエンティティを読み取ることなく、エンティティを削除したり、テーブル全体を切り捨てたりする方法もわかりません。

  • onFlush イベント内のエンティティを削除するにはどうすればよいですか?
  • onFlush イベント内で一括更新 (テーブルの切り捨てと数十万レコードの挿入) を行うにはどうすればよいですか? この場合、 $EntityManager->getConnection()->executeUpdate() を使用できると思いますよね?
  • onFlush イベント内でテーブルをロック (読み取り) するにはどうすればよいですか?
4

1 に答える 1

5

まず第一に、onFlush非常に強力なので、おそらく考えすぎです。

内のエンティティを削除するにはonFlush、リスナーで削除するようにスケジュールするだけです。

public function onFlush(OnFlushEventArgs $eventArgs) {
    $em  = $eventArgs->getEntityManager();
    $uow = $em->getUnitOfWork();

    foreach ($uow->getScheduledEntityUpdates() as $updated) {
        $em->remove($updated);
    }

    $uow->computeChangeSet();
}

一括更新を処理するには、次のことができます。

  • DQL クエリを使用して、処理するエンティティを更新します
  • データフィクスチャ ライブラリのORMPurgerを使用して、テーブルの切り捨てなどの操作を処理します (そのロジックを再現するか、利用可能なメタデータのサブセットと同じ接続を持つ 2 番目のエンティティ マネージャーを使用します)。
  • あなたが言ったように、接続で直接作業してください。あなたはトランザクション中なので、完全に安全です

アプリケーション レベルのオブジェクトを更新せずにデータベースの状態を変更する (一括更新/削除) ことはリスクがあることに注意してください。そのため、このような操作の後にエンティティ マネージャーをクリアすることを検討してください。

ORM には、トランザクション、同時実行性、およびロックに関する完全なドキュメントの章があります。私が知る限り、これらの操作はすべて 中にも有効ですonFlush

于 2013-03-01T14:09:51.300 に答える