-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extra update for self-referencing Many-To-One with NONE generator strategy during persist #7877
Comments
Thank you for opening this issue. Pull requests are welcome if you like to provide one. The PR will also need integration test(s) with an entity close to the one of your example, but with a classic integer id. I assume your example was close to the actual use case of the project you're working on. |
@SenseException PR done #7882 |
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
BaseEntityPersister can save an extra UPDATE query when it persists a self-referencing entity using an application generated identifier Fixes doctrine#7877
Out of curiosity, do you really care about one UPDATE query more or less? Or is the real motivation that a self-referencing (at the class level) association like this has to be defined as NULLable just because of the edge case that an entity might reference itself (at the entity level)? I find the latter argument much stronger. If that’s the case, we should also write the tests in a way to show that the entities can be inserted even with a non-NULLable association, not focus so much on the query count. |
@mpdude The real motivation is having to define a NULLable column. You're right about the test, I'll work on a better version in my PR |
…hen using application-provided IDs The change makes the `BasicEntityPersister` not schedule an extra update in the case of an entity referencing itself and having an application-provided ID (the "NONE" generator strategy). While it looks like a special corner case, the INSERTion of a NULL value plus the extra update require the self-referencing column to be defined as NULLable. This is only an issue for the self-referencing entity case. All other associations work naturally. Fixes doctrine#7877, closes doctrine#7882. Co-authored-by: Sylvain Fabre <[email protected]>
…es for association-target entities that use application-provided IDs (the "NONE" generator strategy). For this generator strategy, we may assume that IDs are already present at the time the insert is executed. The benefit is that now the join column can be defined as not-NULLable, since the ORM no longer uses temporary NULL values. However, care must be taken: Extra updates are not only about the question of having IDs for the associated entities available, but also about having those entities in the database already (to satisfy foreign key constaints). The latter will become easier with doctrine#10547, since the UoW will take care of that detail when computing the commit order. But without that detail, we might break use cases that currently work – that's cases where the extra update gives us the extra time to insert the referred-to entity first. Fixes doctrine#7877, closes doctrine#7882. Co-authored-by: Sylvain Fabre <[email protected]>
…hen using application-provided IDs This change improves scheduling of extra updates in the `BasicEntityPersister`. Extra updates can be avoided when * the referred-to entity has already been inserted during the current insert batch/transaction * we have a self-referencing entity with application-provided ID values (the `NONE` generator strategy). As a corollary, with this change applications that provide their own IDs can define self-referencing associations as not NULLable. I am considering this a bugfix since the ORM previously executed additional queries that were not strictly necessary, and that required users to work with NULLable columns where conceptually a non-NULLable column would be valid and more expressive. One caveat, though: In the absence of entity-level commit ordering (doctrine#10547), it is not guaranteed that entities with self-references (at the class level) will be inserted in a suitable order. The order depends on the sequence in which the entities were added with `persist()`. Fixes doctrine#7877, closes doctrine#7882. Co-authored-by: Sylvain Fabre <[email protected]>
…hen using application-provided IDs This change improves scheduling of extra updates in the `BasicEntityPersister`. Extra updates can be avoided when * the referred-to entity has already been inserted during the current insert batch/transaction * we have a self-referencing entity with application-provided ID values (the `NONE` generator strategy). As a corollary, with this change applications that provide their own IDs can define self-referencing associations as not NULLable. I am considering this a bugfix since the ORM previously executed additional queries that were not strictly necessary, and that required users to work with NULLable columns where conceptually a non-NULLable column would be valid and more expressive. One caveat, though: In the absence of entity-level commit ordering (doctrine#10547), it is not guaranteed that entities with self-references (at the class level) will be inserted in a suitable order. The order depends on the sequence in which the entities were added with `persist()`. Fixes doctrine#7877, closes doctrine#7882. Co-authored-by: Sylvain Fabre <[email protected]>
…hen using application-provided IDs This change improves scheduling of extra updates in the `BasicEntityPersister`. Extra updates can be avoided when * the referred-to entity has already been inserted during the current insert batch/transaction * we have a self-referencing entity with application-provided ID values (the `NONE` generator strategy). As a corollary, with this change applications that provide their own IDs can define self-referencing associations as not NULLable. I am considering this a bugfix since the ORM previously executed additional queries that were not strictly necessary, and that required users to work with NULLable columns where conceptually a non-NULLable column would be valid and more expressive. One caveat, though: In the absence of entity-level commit ordering (doctrine#10547), it is not guaranteed that entities with self-references (at the class level) will be inserted in a suitable order. The order depends on the sequence in which the entities were added with `persist()`. Fixes doctrine#7877, closes doctrine#7882. Co-authored-by: Sylvain Fabre <[email protected]>
…hen using application-provided IDs This change improves scheduling of extra updates in the `BasicEntityPersister`. Extra updates can be avoided when * the referred-to entity has already been inserted during the current insert batch/transaction * we have a self-referencing entity with application-provided ID values (the `NONE` generator strategy). As a corollary, with this change applications that provide their own IDs can define self-referencing associations as not NULLable. I am considering this a bugfix since the ORM previously executed additional queries that were not strictly necessary, and that required users to work with NULLable columns where conceptually a non-NULLable column would be valid and more expressive. One caveat, though: In the absence of entity-level commit ordering (doctrine#10547), it is not guaranteed that entities with self-references (at the class level) will be inserted in a suitable order. The order depends on the sequence in which the entities were added with `persist()`. Fixes doctrine#7877, closes doctrine#7882. Co-authored-by: Sylvain Fabre <[email protected]>
…hen using application-provided IDs This change improves scheduling of extra updates in the `BasicEntityPersister`. Extra updates can be avoided when * the referred-to entity has already been inserted during the current insert batch/transaction * we have a self-referencing entity with application-provided ID values (the `NONE` generator strategy). As a corollary, with this change applications that provide their own IDs can define self-referencing associations as not NULLable. I am considering this a bugfix since the ORM previously executed additional queries that were not strictly necessary, and that required users to work with NULLable columns where conceptually a non-NULLable column would be valid and more expressive. One caveat, though: In the absence of entity-level commit ordering (doctrine#10547), it is not guaranteed that entities with self-references (at the class level) will be inserted in a suitable order. The order depends on the sequence in which the entities were added with `persist()`. Fixes doctrine#7877, closes doctrine#7882. Co-authored-by: Sylvain Fabre <[email protected]>
…hen using application-provided IDs (#10735) This change improves scheduling of extra updates in the `BasicEntityPersister`. Extra updates can be avoided when * the referred-to entity has already been inserted during the current insert batch/transaction * we have a self-referencing entity with application-provided ID values (the `NONE` generator strategy). As a corollary, with this change applications that provide their own IDs can define self-referencing associations as not NULLable. I am considering this a bugfix since the ORM previously executed additional queries that were not strictly necessary, and that required users to work with NULLable columns where conceptually a non-NULLable column would be valid and more expressive. One caveat, though: In the absence of entity-level commit ordering (#10547), it is not guaranteed that entities with self-references (at the class level) will be inserted in a suitable order. The order depends on the sequence in which the entities were added with `persist()`. Fixes #7877, closes #7882. Co-authored-by: Sylvain Fabre <[email protected]>
Fixed by #10735 |
Bug Report
Summary
Using a self-referencing entity with a Many-To-One relationship set during the
__construct()
call with aNONE
strategy for id generation leads to two queries:Current behavior
NULL
for the firstINSERT
[2019-10-23 16:04:21] doctrine.DEBUG: INSERT INTO organization (id, legal_parent_id) VALUES (?, ?, ?, ?, ?, ?, ?) {"1":"[object] (Ramsey\\Uuid\\Uuid: \"c68555b0-f5ae-11e9-914e-38baf82a0624\")","2":null} []
UPDATE
query[2019-10-23 16:04:21] doctrine.DEBUG: UPDATE organization SET legal_parent_id = ? WHERE id = ? ["[object] (Ramsey\\Uuid\\Uuid: \"c68555b0-f5ae-11e9-914e-38baf82a0624\")","[object] (Ramsey\\Uuid\\Uuid: \"c68555b0-f5ae-11e9-914e-38baf82a0624\")"] []
How to reproduce
Expected behavior
INSERT
query withlegal_parent_id
notNULL
[2019-10-23 16:04:21] doctrine.DEBUG: INSERT INTO organization (id, legal_parent_id) VALUES (?, ?, ?, ?, ?, ?, ?) {"1":"[object] (Ramsey\\Uuid\\Uuid: \"c68555b0-f5ae-11e9-914e-38baf82a0624\")","2":[object] (Ramsey\\Uuid\\Uuid: \"c68555b0-f5ae-11e9-914e-38baf82a0624\")} []
Possible solution
This comes from
vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
We could check if
spl_object_hash($newVal) === spl_object_hash($entity)
and ifClassMetadataInfo::GENERATOR_TYPE_NONE === $this->class->generatorType
. If yes, then do not set$newVal = null;
and do not schedule extra update.I can provide a PR if you want
The text was updated successfully, but these errors were encountered: