mirror of
https://github.com/doctrine/orm.git
synced 2026-03-23 22:42:18 +01:00
findBy didn't return back a refresh result #5446
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @jerryladoo on GitHub (Mar 6, 2017).
Originally assigned to: @Ocramius on GitHub.
findByalways returns me back previous entity cached in entity map if I call it in an infinity loop. I created two php file, one is calledkeep_fetching.php, another one is calledtest.php; and also opened up two terminals, one is for 'keep_fetching.php' and another one is fortest.php. I rankeep_fetching.phpfirst and it outputed whatever I have in database as below, which is goodafter that, in another terminal I ran
test.phpto update user's email tobar@hotmail.com, and I was expecting to see the outputs like so:but unfortunately the outputs were still exactly same as the previous one, no any changes.
In order to figure out what is goning on, I dived into the source code, and found that
findByactually did fetch the fresh result from db, but it didn't update the existing entity cached as thehintby default was set toUnitOfWork::HINT_DEFEREAGERLOAD => true, which further resulted in a false to$overrideLocalValuesinside methodcreateEntityinUnitOfWork.php.And from source code, for
findByto update the existing entity is only through theQuery::HINT_REFRESHor clear entire entity map by invoking$em->clear().Now I a little bit confused about what result
findByshould be expected to yield, the cached one or refreshed one? Is there a document that clearly states the relationships betweenfind*methods andQuery::HINT_*?The followings are the two file I was using to do this experiment.
@Ocramius commented on GitHub (Mar 6, 2017):
Closing as invalid.
Specifically, the issue is about a misunderstanding of the behaviour of the UnitOfWork, which is an abstraction around the current open transaction.
Refreshing entities by default would lead to overwritten state of your in-memory entities (which you are working with), whereas what you are doing is executing multiple subsequent reads outside of a serialized transaction (ideal scenario).
The results to be produced by default should always be the in-memory cached ones.
@jerryladoo commented on GitHub (Mar 6, 2017):
@Ocramius thanks for replying this in such short time. But I still have a question about
findBy. If it should always return the cached ones, then why it followed this pattern:instead of the pattern
finduses:?
@chrisdlangton commented on GitHub (Mar 7, 2017):
@jerryladoo
Reading
entity-state;http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#entity-state
and
unitofwork-being-out-of-sync;http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#effects-of-database-and-unitofwork-being-out-of-sync
It is quite clear that both
findandfindBywhen called in a single php process, will;findorfindByreturn an Entity with data from the database recordUnitOfWork::STATE_MANAGEDin both casesfindorfindByin the same php process will return same Entity, with the same data as the first call.Per
transactions-and-concurrency;http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency.html
@Ocramius I assume calling
flushat any point after the first call and any subsequent calls should force Doctrine to fetch fresh data from database, asEntityManager#flush()completes the transaction and therefore the Entity and it's data is released.Conclusion: for fresh data between calls, call
EntityManager#flush()which completes the previous calls open transaction.@jerryladoo commented on GitHub (Mar 7, 2017):
@chrisdlangton thanks for bringing up the docs
This is what doc says, and it is a result I am expecting, and it is only one I have question about not others. But the actual result is not always from db(only first time to be specific), it is from cached by default (confirmed by @Ocramius and the source code itself), and @Ocramius also explained why by default it should always return the in-memory cached ones. You can run the two scripts above to see the actual result.
@farazpartoei commented on GitHub (Dec 11, 2018):
I know its a little bit late! but I used
EntityManager:refreshmethod and issue was recovered@k00ni commented on GitHub (Feb 4, 2020):
For documentation purposes on a similar issue, because it might not be a bug, but AFAIK less known behavior.
When running update operations on the same database inside the same script using
EntityManagerand a DBAL connection, you might get cached results after changes to the database, even if you runEntityManager::flushin between.Solution: I solved it by calling EntityManager::clear after running an update command with DBAL connection. Unfortunately the "Synchronization with database" doesn't contain any information about that.
In the following some example code to illustrate it:
Thank your for raising the issue and give helpful hints.