2016-02-24 13 views
12

私は既存のIdで新しいエンティティを作成し、関連するデータベースレコードを更新します。Doctrine merge:DateTimeフィールドは常に更新されます

Doctrine merge は私の親友です:変更があるかどうかを確認し、正しい更新クエリを生成します。

$entity = new Entity(); 
$entity->setId(1); 
$entity->setName('test'); 
$EntityManager->merge($entity); 
$EntityManager->flush(); 

仮定そのIDを持つ要素= 1既にDBに存在する:私は、コードを再度実行する場合

UPDATE table SET name = ? WHERE id = ? ["test","1"] 

:名前が「テスト」と異なる場合、教義は、このクエリを生成しますDoctrineは何も変更されていないことを認識し、クエリはコミットされません。

私はDateTimeフィールドを設定したときに変更し、常に更新クエリを実行するようは、教義はそれを考慮

しかし...:

$entity = new Entity(); 
$entity->setId(1); 
$entity->setDate(new \DateTime(2000-01-01)); 
$EntityManager->merge($entity); 
$EntityManager->flush(); 
//* ALWAYS commits this query: 
>> UPDATE table SET date = ? WHERE id = ? ["2000-01-01 00:00:00","1"] 

あなたはこの無用の更新を回避する方法を知っていますか?ありがとう!

答えて

5

どうやら行動が期待されていることを

Githubを参照)まだ解決されていない教義のバグのようですだ@Raymondで言ったように、オブジェクトは、参照

+11

典型的なプログラマーのアプローチ:もしあなたがそのバグを解決できないなら、それをFeature!_;)としてマークしてください – T30

+0

私は彼らの理由に同意しなかったので、ほとんど落胆しましたXD – andho

+0

Javaのequalsとhashメソッドは、 。 – andho

7

によって比較され、期待される動作です。

それは残念だが、あなたのマージがdate性質に依存していない場合、回避策は、このようなマージ後の日付を設定することができます。

$entity = new Entity(); 
$entity->setId(1); 
// Set all fields that the merge is depending on 
// ... 
$EntityManager->merge($entity); 

$entity->setDate(new \DateTime('2000-01-01')); 
$EntityManager->flush(); 

更新

後試みたが、唯一の選択肢は、マージされたオブジェクトを取得し、再びEntityManagerをフラッシュすることによって更新されるようだ。

を使用でき

$entity = new Entity(); 
$entity->setId(1); 
// Set all fields that the merge is depending on 
$EntityManager->merge($entity); 
$EntityManager->flush(); 

$entity = $EntityManager->getRepository('Your\Entity')->find(1); // Retrieve the entity 
$entity->setDate(new \DateTime('2000-01-01')); 
$EntityManager->flush(); // Reflush 

アップデート2

私は、マージ後に更新を達成することが分かっきれいな方法は、例えば、再マージするエンティティであります:

$entity = new Entity(); 
$entity->setId(1); 
// Set all fields that the merge is depending on 
$EntityManager->merge($entity); // The real merge that retrieve (without commit) or create 
$EntityManager->flush(); 

$entity->setDate(new \DateTime('2000-01-01')); 
$entityManager->merge($entity); // Remerge the object with the changed field 
$EntityManager->flush(); // Working re-flush 

しかし、これは主要な問題を変更しないと自分でDateTimeオブジェクトを比較することはできませんので、実際にも、最初のマージ後、setDateを呼び出す前$entity->getDate()リターンは常にnull、意味がありません。

Doctrineは、参照(ハッシュ)を===で比較し、\DateTimeという新しいインスタンスも、オブジェクトの日付が変更されていない場合でも更新を行います。

これは、比較演算子として==を用いて固定することができ、本当に問題の問題ですが、教義は彼らの一般的なオブジェクト比較メカニズムを壊すことなく\DateTimeのための具体的な条件を作ることができない、それはほとんどの1の性能を低下させるために必要使用された機能。

+0

申し訳ありません。私は正しくテストしませんでした。変更された場合、日付は更新されません。日付を一切設定しないと、同じ動作をするようです。 – T30

+0

エンティティが新規の場合、日付は正しく設定されていますか?しかし、それが更新であれば? – chalasr

+0

エンティティが作成されてもdate = NULLのままにします。new:マージコマンドの後に行われたすべての変更を無視しているようです(Date以外のフィールドを設定した場合も同様です)。具体的には、 '$ entity-> getDate()'をダンプすると、設定された日付が出力されます。しかし、フラッシュするとき、日付はNULLとしてコミットされます。 – T30

関連する問題