Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knowing when to call persist

I'm using Doctrine 2 as my ORM, and things are going well, but I've been wondering about the EntityManager#persist() method. The "Persisting entities" documentation says the following about a call to persist() for object X:

If X is a preexisting managed entity, it is ignored by the persist operation.

That leads me to believe that persist() need only be called when the object is new and has not yet been saved to the database. However, the documentation for the "Deferred Explicit" change tracking policy says:

... Doctrine 2 only considers entities that have been explicitly marked for change detection through a call to EntityManager#persist(entity) ...

... which sounds like persist() must be called on the object for it to be updated at all. When should persist() be called? If only on new objects, is there a significance performance hit to call it anyway whenever an entity is updated and let Doctrine sort out the difference?

like image 963
Derek Stobbe Avatar asked Aug 31 '11 20:08

Derek Stobbe


2 Answers

With the Deferred Explicit policy (it's not the default policy), you need to explicitly call persist() on each modified entity for doctrine to persist them. (Except for cascade-persist associations.)

Doctrine still needs to compare the new value of each property with the original value to know which property to update, so this may have a performance hit if you persist() too much entities.

With the default change tracking policy you only need to call persist on entities that are not yet managed by Doctrine (entities that you created with new). With this policy, when you call flush() doctrine automatically detects which entities have been updated and need to be persisted.

like image 60
Arnaud Le Blanc Avatar answered Oct 22 '22 21:10

Arnaud Le Blanc


The documentation is somewhat misleading. In implicit tracking mode, all entities have a state (managed, removed, detached etc.); entities obtained by find() and similar methods (basically everything which is not created with new) are already in managed state. On flush(), all managed (and removed) entites are checked for changes and, if necessary, updated in the DB.

In explicit tracking mode, there is an additional dirty check list, and persist() adds the object (and possibly associated objects, depending on cascade settings) to that list. Only items on the dirty check list are considered for update. The dirty check list is cleared after flushing, so if you do a second flush, and change the same object again, you must call persist() once more. (In contrast, the managed state is kept after flush.)

You can check the details for yourself in the Doctrine\ORM\UnitOfWork class; search for isChangeTrackingDeferredImplicit / isChangeTrackingDeferredExplicit (those are the only places where behavior differs under the two policies).

like image 20
Tgr Avatar answered Oct 22 '22 21:10

Tgr