mirror of
https://github.com/doctrine/orm.git
synced 2026-03-23 22:42:18 +01:00
Deprecate EntityManager::flush with $entity argument #6624
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 @beberlei on GitHub (Feb 6, 2021).
The method
EntityManager::flushhas an optional argument $entity (either accepting a single entity or array of entities) that when passed are the only set of entities considered in compute changeset operation. The idea originally was to allow more performant flush operations when a lot of entities are in the identity map.However due to restrictions in how the UnitOfWork operates, it had to also "flush" other entities sometimes that were not passed to
flush, making the operation inconsistent.As such we decided to deprecate this approach to flushing and only allow a full flush for now.
Alternative: If you want to keep the set of entities small that flush operates on, you could decide to use the explicit change tracking policy for an entity instead of the implicit one. https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/reference/change-tracking-policies.html
@miedzikd commented on GitHub (Sep 6, 2021):
Hello @beberlei :)
Can you give me another tip, how can I solve my issue when flushing objects as parameters, will it be deprecated?
I have one huge table with Orders. It's used in a lot of places in the system.
Normally we use
->flush()without passing Order object as a parameter, but I have one command job that regenerates all Orders. Im doing that in batch for 1000 orders per execution.If I pass Order object to flush - whole execution take more or less 60s. Without that 1200s, because size of unitOfWork is too huge.
Explicit change tracking policy can be apply on whole entity level only? I can't change this because it is used in too many places. Can I apply the policy only in one action? or one command?
Greetings from Poland :)
@wadjeroudi commented on GitHub (Nov 21, 2021):
@beberlei @Ocramius any news on this deprecation ? We should be able to do a specific data change at least in a new transaction without flushing the whole changes.
Maybe some sort of temporary clear() on entityManager and restore the unit of work after :
I'm probably wrong but adding a property on EntityManager $savedUnitOfWork to store the current uof, instantiate a new empty one seems pretty simple imho :
@poolerMF commented on GitHub (Dec 22, 2021):
+1
@Fedik commented on GitHub (Dec 23, 2021):
It already possible, if I right understood the linked doc.
We have to define
DEFERRED_EXPLICITfor ChangeTrackingPolicy.Then
flush()operation will take in count only an entities that was explicitly marked to "persist" with$em->persist($entity).Old:
New:
Set mapping to
DEFERRED_EXPLICIT, and:@GDXbsv commented on GitHub (Dec 23, 2021):
@Fedik I see a problem with it:
If you not set DEFERRED_EXPLICIT as default and only one possible value for all entities, then if some other entity was changed in a different place without DEFERRED_EXPLICIT then this entity will be saved as well. So we still can not prevent flushing unexpected entities.
@Fedik commented on GitHub (Dec 23, 2021):
That correct, and that why you have to be sure all your Entities is set to DEFERRED_EXPLICIT(or NOTIFY) and that you call
$em->persist($entity)when changes need to be written.Unless your App requires different. I think.
@aniolekx commented on GitHub (Feb 21, 2022):
Is it possible to set ChangeTrackingPolicy per script execution? I am happy enough that whole app is set to Deferred Implicit, but for data upload from excel files I need Deferred Explicit, removing of that option will add me a lot of work (I will have to check whole app where we have missing persist)
@derrabus commented on GitHub (May 11, 2022):
Fixed via #9485.
@kgasienica commented on GitHub (Aug 9, 2022):
There were any discussion about that? This change makes many scripts in batches last way much longer. And what is even worse, since this change you can no longer be sure which things are flushed.
If I have to be honest, I don't really like this change.
@beberlei commented on GitHub (Aug 9, 2022):
@kgasienica its deprecated yes, but we also plan to introduce an alternative that is better.
Just keep using the deprecated way until then
@kgasienica commented on GitHub (Aug 9, 2022):
Okay, thank you. It is really breaking-change thing that is changing the way entities have to be managed in our applications.
@wadjeroudi commented on GitHub (Oct 7, 2022):
@beberlei any information on the new alternative please ?
@wadjeroudi commented on GitHub (Jan 19, 2023):
@beberlei @greg0ire it seems that the alternative was this one but @Ocramius won't work on it anymore by lack of time I guess.
https://github.com/doctrine/orm/issues/5550#issuecomment-1301849227
Still same approach ? or an other is considered ?
@phpws commented on GitHub (Sep 26, 2023):
there are probably cases that I can't think of where this wouldn't work, but thought to share it incase it could be useful.
If the existing flush method was renamed to something like
flushAlland made private and passing in an entity was removed from the method, then the flush method was replaced with this, then it seems like this could work, at least for my case where I am using it does, but maybe you will know reasons as to why it can't be done like this, maybe it would still be inconsistant in some cases.@beberlei commented on GitHub (Sep 27, 2023):
@phpws Please don't do that :-)
@phpws commented on GitHub (Sep 29, 2023):
@beberlei ok, I didn't in the end, don't worry :-D, I take it that would have adverse affects on other things, performance for one would probably be a problem on large projects with huge sets of scheduledEntites collections, also it doesn't account for updates.
@wadjeroudi commented on GitHub (Jan 29, 2024):
@beberlei @greg0ire you released the doctrine 3.0 RC1, congrats, what about this BC BREAK
https://github.com/doctrine/orm/blob/3.0.x/UPGRADE.md#bc-break-removed-ability-to-partially-flushcommit-entity-manager-and-unit-of-work
there's still no alternative ?
@greg0ire commented on GitHub (Jan 29, 2024):
@wadjeroudi I'm told that using
detach()(it's been undeprecated) would be an alternative for you, as partial flushing should be equivalent to detaching things you don't want toflushand then callingflush()@wokenlex commented on GitHub (Apr 5, 2024):
So, the real way to work with it normally, is to make handwritten queries, like in old times?
I mean, sometimes you need to do something under the hood - write do database log, cache some items, but you don't wan't to ruin the main business logic.
@CsabaNa commented on GitHub (Jun 12, 2024):
So how can we insert/flush only one Entity e.g. I need a record ID in multiple places but based on this record some other entities could change so I don't want to inc the server load to insert one and update the others Then again update several records so updating at least twice i would insert one do the stuff and update once....
@thereisnobugs commented on GitHub (Oct 29, 2024):
And... where is an alternative?
@yakobe commented on GitHub (Mar 21, 2025):
@beberlei Please could you provide some information on the better alternative? Many thanks.
@jurchiks commented on GitHub (May 27, 2025):
This change is now causing me a lot of problems.
I never used
flush($entity), but now I have a need for it, because I have some code that would greatly benefit from it due to some code being called tens of thousands of times in one cron job. I know that callingflush()tens of thousands of times would absolutely murder the performance that's already not great, and I don't need to flush everything, I only need to flush the changes that I want. At the same time, I obviously do not want to rewrite my entire codebase to manually flush everything, because that would be a ridiculous amount of work, all because some people thought that they know better than everyone else using their library.I don't care about this "problem", it doesn't affect my use case. I want to flush a single entity that does not affect any other entity (it has only parent relations to entities that already exist in the database, and they're one-way relations). This change has made it impossible, and your suggested "fix" is to add DEFERRED_EXPLICIT to all entities and manually persist them everywhere.
This is a shit change that does more bad than good for the people who had any use of
flush($entity)at all. All you needed to do is add a disclaimer in the method's PHPDocs about the potential issue.And it has been over 3 years since the promised "better alternative" that is yet to be seen. You should have implemented the "better alternative" before you removed this! This is backwards as hell!
@Ocramius commented on GitHub (May 27, 2025):
There's no alternative due to how the UnitOfWork is designed: you need to size your batch jobs accordingly.
The alternative is a different architectural pattern, not part of this ORM, and that is fine.
@jurchiks commented on GitHub (May 28, 2025):
So when beberlei wrote:
He lied? Did you ever actually plan on doing this? If yes, what changed? Why didn't you give an official commentary on the status of this thing here?
You can downvote me all you want - two can play this game -, but that doesn't save the situation at all.
@beberlei commented on GitHub (May 29, 2025):
I still plan to do this, but all my time here is voluntary so 🤷 cant say when.
@jurchiks commented on GitHub (May 31, 2025):
Then you shouldn't have removed this feature and shouldn't have promised a replacement. 3+ years...
@Fipschen commented on GitHub (May 31, 2025):
@jurchiks I think it's time to cool down a bit. Don't forget, he's also just a human who guess respect.
@Arkemlar commented on GitHub (Jul 28, 2025):
Actually, I agree with @jurchiks. Removing such kind of feature without replacement is painful and, honestly, not respectful to users - because it forces them to search for hacks. Multiply this problem by the number of affected users and... well.
It is fine to write notice right inside flush's phpdoc that doing
flush($object)leads to inconsistency, etc., but let users decide. May be they know what they doing.