2016-02-24 15 views
12

Creo una nuova entità con uno esistente Id e desidero aggiornare il record del database correlato.Unisci doctrine: campo DateTime sempre aggiornato

Doctrine merge è stato il mio migliore amico: riconosce se ci sono cambiamenti e genera la query di aggiornamento corretta.

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

Supponiamo che l'elemento con l'id = 1 già esiste nella db: se il nome è diverso da 'prova', Doctrine genera questa ricerca:

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

Se eseguire nuovamente il codice sopra, Doctrine riconosce che nulla è cambiato e nessuna query è stata commessa.

Ma ... quando ho impostato un campo datetime, Dottrina considerano come modificato e corre sempre la query di aggiornamento:

$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"] 

Sai un modo per evitare questo aggiornamento inutile? Grazie!

risposta

5

Apparentemente è sembra essere un bug in dottrina che non è ancora risolto (Riferimento Github)

che ci si aspetta un comportamento, gli oggetti vengono confrontate con riferimento

+11

Tipico approccio del programmatore: _Se non riesci a risolvere il bug, contrassegnalo come una caratteristica! _;) – T30

+0

Ti ho quasi svalutato perché non ero d'accordo con il motivo XD – andho

+0

I metodi di equità e hash di Java sono davvero appropriati qui . – andho

7

Come detto da @Raymond, è il comportamento previsto.

E 'un peccato, ma se la stampa non dipende proprietà date, una soluzione potrebbe essere quella di impostare la data dopo l'unione in questo modo:

$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(); 

Aggiornamento

Dopo provato, l'unica alternativa sembra recuperare l'oggetto unito e aggiornarlo lavandolando di nuovo EntityManager.

È possibile utilizzare:

$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 

Update2

Il modo più pulito che ho trovato per ottenere l'aggiornamento dopo l'unione è ri-unire l'entità, per esempio :

$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 

Ma questo non cambia il problema principale e non ha molto senso perché non si può confrontare l'oggetto DateTime da soli, $entity->getDate() ritorno sempre null prima di chiamare setDate, anche dopo la prima unione.

Doctrine confronta gli oggetti per riferimento (cancelletto) con ===, anche una nuova istanza di \DateTime causa l'aggiornamento anche se la data dell'oggetto è invariata.

Questo è un problema molto problematico che potrebbe essere risolto utilizzando == come operatore di confronto, ma dottrina non può fare una condizione specifica \DateTime senza rompere il loro meccanismo confronto oggetti generico, che coinvolge a diminuire le prestazioni di uno dei più funzione usata

+0

Spiacente di non averlo testato correttamente: non aggiorna la data se cambiata: sembra che si comporti allo stesso modo se non si imposta la data. – T30

+0

Nel caso che l'entità sia nuova, la data è impostata correttamente? Ma non se è un aggiornamento? – chalasr

+0

Lascia la data = NULL anche se l'entità è stata creata nuova: sembra ignorare tutte le modifiche apportate dopo il comando di unione (anche se imposto altri campi oltre alla Data). Nello specifico, se eseguo il dump di '$ entity-> getDate()' stampa la data impostata. Ma quando lo svuotamento, la data è impegnata come NULL. – T30