A set of recombinant entity changes in an onFlush listener

Consider the following scheme:

[Work] id tags ManyToMany(targetEntity="Tag", inversedBy="works", cascade={"persist"}) [Tag] id works_count works ManyToMany(targetEntity="Work", mappedBy="tags") 

works_count is the cache counter for Tag::works .

I have an onFlush Job listener that checks if Work::tags has changed and updates each of the works_count tags.

 public function onFlush(OnFlushEventArgs $args) { foreach ($uow->getScheduledEntityUpdates() as $work) { $changedTags = /* update relevant tags and return all the changed ones */ $metadata = $em->getClassMetadata('Acme\Entity\Tag'); foreach ($changedTags as $tag) { $uow->recomputeSingleEntityChangeSet($metadata, $tag); } } } 

Now, if I read the changes to the updated tag sets, the works_count changes works_count displayed correctly , but they are not updated in the database ..

If I replaced recomputeSingleEntityChangeSet() with computeChangeSet() , then everything will work as expected and the database will update , but computeChangeSet () has @internal Don't call from the outside. annotation on it, so I'm not sure what the consequences are ..

Every Internet source says use recomputeSingleEntityChangeSet , so why doesn't it work in this case?

PS Tags are managed by EntityManager ( $em->contains($tag) returns true)

+4
source share
3 answers

This problem was due to a bug in UnitOfWork and was finally fixed with the release of Doctrine ORM 2.4.3 dated September 11, 2014. For more details, see DDC-2996 .

+3
source

It seems that Doctrine 2.2 can merge change sets or create new change sets, but she should know that. If you make a mistake, it will either replace your existing change sets or do nothing. I would be very interested to know if there is a better option than this, or if it is even correct.

  if($uow->getEntityChangeSet($entity)) { /** If the entity has pending changes, we need to recompute/merge. */ $uow->recomputeSingleEntityChangeSet($meta, $contact); } else { /** If there are no changes, we compute from scratch? */ $uow->computeChangeSet($meta, $entity); } 
+2
source

In doctrine 2.4.1, use recomputeSingleEntityChangeSet only if you change the tag in the event listener and the UOW contains the ChangeSet tag (a change that occurs outside the event listener). Basically, recomputeSingleEntityChangeSet is a function to merge ChangeSet for an object.

Doc from function The passed object must be a managed object. If the object already has a set of changes, because this method is called during the commit cycle, then change shifts are added, as a result of which the changes detected in this method prevail.

NOTE. You must make sure that the UOW already has a ChangeSet for the object, otherwise it will not merge.

+1
source

Source: https://habr.com/ru/post/1481263/


All Articles