2011-08-31 14 views
7

Sto usando Doctrine 2 come mio ORM, e le cose stanno andando bene, ma mi sono chiesto il metodo EntityManager#persist(). La documentazione "Persisting entities" dice quanto segue riguardo una chiamata a persist() per oggetto X:sapere quando chiamare persiste

Se X è un'entità preesistente gestito, viene ignorato dall'operazione di persistere.

Questo mi porta a credere che persist() debba essere chiamato solo quando l'oggetto è nuovo e non è stato ancora salvato nel database. Tuttavia, la documentazione per il "Deferred Explicit" change tracking policy dice:

... Doctrine 2 considera solo gli enti che sono stati esplicitamente contrassegnati per il rilevamento cambiamento attraverso una chiamata a EntityManager # persistere (entità) ...

... che suona come persist() deve essere richiamato sull'oggetto per essere aggiornato. Quando si deve chiamare persist()? Se solo su nuovi oggetti, c'è un impatto significativo sulle prestazioni per chiamarlo comunque ogni volta che un'entità viene aggiornata e lasciare che Doctrine risolva la differenza?

risposta

8

Con Deferred Explicit policy (non è la politica di default), è necessario chiamare esplicitamente persist() su ciascuna entità modificata affinché doctrine possa persisterli. (Tranne associazioni a cascata persistenti.)

Doctrine ha ancora bisogno di confrontare il nuovo valore di ogni proprietà con il valore originale per sapere quale proprietà aggiornare, quindi questo potrebbe avere un impatto sulle prestazioni se si dispone di troppe entità persist().

Con default change tracking policy è necessario richiamare solo le entità non ancora gestite da Doctrine (entità create con new). Con questa politica, quando si chiama flush() la doctrina rileva automaticamente quali entità sono state aggiornate e devono essere mantenute.

+0

Si noti che quando si utilizza il rilevamento delle modifiche implicite differite (impostazione predefinita), Doctrine confronterà il valore originale con il nuovo valore per ogni proprietà (finora uguale a Differito differito) per ogni entità presente in UnitOfWork e non solo quelli che hai chiamato 'persist()' on. –

+3

Ho vissuto metà della mia vita fino a quando il problema non ha destato il pensiero che la politica di default è la politica Deferred Explicit. –

6

La documentazione è in qualche modo fuorviante. In modalità di tracciamento implicita, tutte le entità hanno uno stato (gestito, rimosso, rimosso, ecc.); entità ottenute da find() e metodi simili (in pratica tutto ciò che non è stato creato con new) sono già in stato gestito. Su flush(), tutte le entrate gestite (e rimosse) vengono controllate per le modifiche e, se necessario, aggiornate nel DB.

Nella modalità di tracciamento esplicito, è presente un elenco di controllo sporco aggiuntivo e persist() aggiunge l'oggetto (e gli oggetti eventualmente associati, in base alle impostazioni di cascata) a tale elenco. Solo gli articoli nell'elenco di controllo sporco vengono considerati per l'aggiornamento. L'elenco di controllo sporco viene cancellato dopo lo svuotamento, quindi se si esegue un secondo svuotamento e si modifica di nuovo lo stesso oggetto, è necessario chiamare ancora persist(). (Al contrario, lo stato gestito viene mantenuto dopo lo svuotamento.)

È possibile verificare personalmente i dettagli nella classe Doctrine\ORM\UnitOfWork; cerca isChangeTrackingDeferredImplicit/isChangeTrackingDeferredExplicit (questi sono gli unici posti in cui il comportamento differisce in base alle due norme).

+0

Ho un'entità distaccata (canale) proveniente da un set di risultati memorizzato nella cache che devo aggiungere dati solo alla tabella dei dati. C'è un modo per mantenere i dati del canale senza unire il canale distaccato? – andig

+0

@andig, non sono sicuro. Immagino tu parli di [questa domanda] (http://stackoverflow.com/questions/18102728/doctrine-persisting-detached-entities) - perché hai bisogno di mantenere il canale quando vuoi davvero aggiungere una nuova entità di dati? – Tgr

+0

ottima domanda. Sto lavorando con il codice legacy e sono ancora nuovo in Doctrine. Indagherò come/se posso mantenere la ArrayCollection dei 'dati' direttamente. Se lavorassi, apprezzerei una risposta incrociata per poter votare. – andig

Problemi correlati