2011-08-31 13 views
7

Estoy usando Doctrine 2 como mi ORM, y las cosas van bien, pero me he estado preguntando sobre el método EntityManager#persist(). La documentación "Persisting entities" dice lo siguiente acerca de una llamada a persist() por objeto X:saber cuándo llamar persistir

Si X es una entidad gestionada preexistente, es ignorado por la operación de persistir.

Eso me lleva a creer que persist() solo necesita ser llamado cuando el objeto es nuevo y aún no se ha guardado en la base de datos. Sin embargo, la documentación de la "Deferred Explicit" change tracking policy dice:

... Doctrina 2 sólo se tiene en cuenta las entidades que se han marcado explícitamente para la detección de cambio a través de una llamada a EntityManager # persist (entidad) ...

... que suena como persist() debe invocarse en el objeto para que se actualice en absoluto. ¿Cuándo se debe llamar al persist()? Si solo se trata de objetos nuevos, ¿hay un impacto significativo en el rendimiento para llamarlo de todos modos cada vez que se actualiza una entidad y dejar que Doctrine clasifique la diferencia?

Respuesta

8

Con el Deferred Explicit policy (no es la política predeterminada), debe llamar explícitamente a persist() en cada entidad modificada para que la doctrina los persista. (Excepto para las asociaciones persisten en cascada.)

Doctrine aún necesita comparar el nuevo valor de cada propiedad con el valor original para saber qué propiedad actualizar, por lo que puede tener un rendimiento si persist() demasiadas entidades.

Con el default change tracking policy solo necesita llamar para persistir en las entidades que aún no están administradas por Doctrine (entidades que creó con new). Con esta política, cuando llamas a flush() la doctrina automáticamente detecta qué entidades se han actualizado y necesitan persistir.

+0

Tenga en cuenta que al usar el seguimiento de cambios implícitos diferidos (el valor predeterminado), Doctrine comparará el valor original con el nuevo valor de cada propiedad (hasta el momento diferido explícito) para cada entidad que esté en UnitOfWork, y no solo los que llamó 'persist()' encendidos. –

+3

Viví la mitad de mi vida hasta que surgió el problema con el pensamiento de que la política predeterminada es Política explícita diferida. –

6

La documentación es un poco engañosa. En el modo de seguimiento implícito, todas las entidades tienen un estado (gestionado, eliminado, desconectado, etc.); entidades obtenidas por find() y métodos similares (básicamente todo lo que no se creó con new) ya se encuentran en estado gestionado. En flush(), se verifican todas las entidades administradas (y eliminadas) para ver si hay cambios y, si es necesario, se actualizan en la base de datos.

En el modo de seguimiento explícito, hay una lista de comprobación adicional sucia, y persist() agrega el objeto (y posiblemente los objetos asociados, según la configuración de cascada) a esa lista. Solo los elementos en la lista de verificación sucia se consideran para actualización. La lista de verificación sucia se borra después de enjuagar, por lo que si realiza una segunda descarga y vuelve a cambiar el mismo objeto, debe llamar al persist() una vez más. (En contraste, el estado administrado se mantiene después de la descarga.)

Puede verificar los detalles en la clase Doctrine\ORM\UnitOfWork; busque isChangeTrackingDeferredImplicit/isChangeTrackingDeferredExplicit (esos son los únicos lugares donde el comportamiento difiere bajo las dos políticas).

+0

Tengo una entidad separada (canal) que viene del conjunto de resultados en caché al que necesito agregar datos, que solo afecta a la tabla de datos. ¿Hay alguna forma de conservar los datos del canal sin fusionar el canal separado? – andig

+0

@andig, no estoy seguro. Supongo que está hablando de [esta pregunta] (http://stackoverflow.com/questions/18102728/doctrine-persisting-detached-entities) - ¿Por qué necesita mantener el canal cuando realmente solo quiere agregar una nueva entidad de datos? – Tgr

+0

excelente pregunta. Estoy trabajando con código heredado y todavía soy nuevo en Doctrine. Investigare cómo/si puedo persistir con la colección de datos de Array directamente. Si trabaja, agradecería una respuesta cruzada para poder votar. – andig

Cuestiones relacionadas