web-dev-qa-db-ja.com

ORMでエンティティをデタッチおよびマージする必要があるのはなぜですか?

質問はDoctirneについてですが、それは多くのORMに拡張できると思います。

切り離す:

エンティティはEntityManagerからデタッチされるため、エンティティでEntityManager#detach($entity)メソッドを呼び出したり、デタッチ操作をカスケードしたりすることによって管理されなくなります。デタッチされたエンティティに加えられた変更(エンティティの削除を含む)は、エンティティがデタッチされた後はデータベースに同期されません。

マージ:

エンティティのマージとは、(通常は切り離された)エンティティをEntityManagerのコンテキストにマージして、それらが再び管理されるようにすることです。エンティティの状態をEntityManagerにマージするには、EntityManager#merge($entity)メソッドを使用します。渡されたエンティティの状態は、このエンティティの管理されたコピーにマージされ、その後、このコピーが返されます。

私はこれがどのように機能するかを(ほぼ)理解していますが、問題は、なぜエンティティをデタッチ/マージする必要があるのか​​ということです。これらの2つの操作を使用/必要とする場合の例/シナリオを教えてください。

18
gremo

エンティティをいつ切り離す必要がありますか?
EMからのエンティティの分離(EntityManager)は、複数のEMを処理し、同時実行の競合を回避する場合に広く使用されます。次に例を示します。

$user= $em->find('models\User', 1);
$user->setName('Foo');

// You can not remove this user, 
// because it still attached to the first Entity Manager
$em2->remove($user);
$em2->flush();

そのセッションはデータベースから最初に$userをロードする$em2に属しているため、$emによって$userオブジェクトを制御することはできません。上記の問題を解決する方法は?オブジェクトをデタッチする必要があります:

$user= $em->find('models\User', 1);
$user->setName('Foo');

$em2->detach($user);
$em2->remove($user);
$em2->flush();

いつマージ機能を使うべきですか?
基本的にエンティティを更新する場合:

$user= $em->find('models\User', 1);
$user->setName('Foo');

$em->merge($user);
$em->flush();  

EMは、データベース内の$ userとメモリ内の$ userを比較します。 EMは、変更されたフィールドを認識すると、それらを更新するだけで、古いフィールドを保持します。

flushメソッドはコミットをトリガーし、ユーザー名はデータベースで更新されます

18
manix

並行性の問題を処理するときは、エンティティを切り離す必要があります。

プロジェクトへのコールバックを作成する非同期APIを使用しているとします。コールバック命令とともにAPI呼び出しを発行する場合、コールバックの影響を受けるエンティティを引き続き管理している可能性があるため、コールバックによって行われた変更を上書きします。

1
NicParry

データベースに永続的なデータがある場合はエンティティをデタッチすることもできますが、コードではユーザーアカウントに応じてこのエンティティを変更します。

たとえば、いくつかのキャラクターといくつかの攻撃が戦うブラウザゲーム。 AttackOne "UserFoo"(lvl 90)で使用されるものは、 "UserBarr"(lvl 20)で使用されるよりも優れたボーナスによって変更されますが、データベースではAttackOne常に同じ攻撃

0
Artur R.