DDC-1361: DQL Hydrate issues with PK composed with composite FK seemingly making collections loaded twice #1707

Closed
opened 2026-01-22 13:22:56 +01:00 by admin · 5 comments
Owner

Originally created by @doctrinebot on GitHub (Sep 4, 2011).

Originally assigned to: @beberlei on GitHub.

Jira issue originally created by user cammanderson:

Environment/Scenario:

ENTITIES:

Page Entity (page)

  • page.id as PK
  • page.elements One to Many to entity elements (w/ ArrayCollection)

Elements Entity (element)

  • element.id AS PK
  • page (Many to One)
  • elementVersions One to Many to elementVersions entity (w/ ArrayCollection)

ElementVersion Entity (elementVersion)

  • element AND elementVersion.versionId as PK (note this is a PK composed of FK)
  • element Many to One to element entity

Repository

When using my Node Repository I do a DQL with all the joins, e.g.
DQL: SELECT page, element, elementVersions FROM page JOIN page.elements AS element JOIN page.elementVersion AS elementVersion WHERE page.id = :pageId.

By doing this all the data is loaded correctly. This is shown by doing a var_dump on a HYDRATE_ARRAY. The structure is correct. There is one thing that appears missing elementVersion.element, therefore not having a complete PK present (TBD). I would think that there should be a reference back to the parent (element).

I then switched back to hydrating my entity objects as normal. I should have loaded all the data into the collections therefore stopping any need to do subsequent DB calls.

Problem/Bug

When I access the collection for the versions (e.g. page.elements.elementVersions) the elementVersions are reloaded again from the database. (e.g. A new SQL call is made to the server), even though my first join had loaded the data.

I believe that when it is using a FK in the PK composition it is not correctly seeing it has loaded the data already.

Weird Behaviour

If I do a DQL that joins the relationship back, I can avoid the database reloading the collection again:

SELECT page, element, elementVersion, elementVersionElement FROM page JOIN page.elements AS element JOIN page.elementVersions AS elementVersion JOIN elementVersion.element AS elementVersionElement WHERE page.id = :pageId.

By joining the table that is used for the FK/PK scenario back onto itself it prevents another SQL call being made when I attempt to access page.elements.elementVersions.

If I switch back to HYDRATE_ARRAY, I can see that now the elementVersions have the element variable, and it appears that this allows it to identify that it has it in the collection and no-longer needs to re-run SQL to locate the object again.

This results in unavoidable additional SQL calls for each element that exists on the page (scales proportionate to number of elements).

My Thoughts

I am thinking that in the hydrate process it is not setting the FK relationship of elementVersion.element, causing Doctrine to attempt to re-run SQL to obtain the collection again (maybe because it thinks that the objects do not have valid/complete PK). I think somewhere the mapping when it creates the objects is just missing the bit where the proxy gains a value for this property back to the parent.

Originally created by @doctrinebot on GitHub (Sep 4, 2011). Originally assigned to: @beberlei on GitHub. Jira issue originally created by user cammanderson: # Environment/Scenario: ## ENTITIES: Page Entity (page) - page.id as PK - page.elements One to Many to entity elements (w/ ArrayCollection) Elements Entity (element) - element.id AS PK - page (Many to One) - elementVersions One to Many to elementVersions entity (w/ ArrayCollection) ElementVersion Entity (elementVersion) - element AND elementVersion.versionId as PK (note this is a PK composed of FK) - element Many to One to element entity ## Repository When using my Node Repository I do a DQL with all the joins, e.g. DQL: SELECT page, element, elementVersions FROM page JOIN page.elements AS element JOIN page.elementVersion AS elementVersion WHERE page.id = :pageId. By doing this all the data is loaded correctly. This is shown by doing a var_dump on a HYDRATE_ARRAY. The structure is correct. There is one thing that appears missing elementVersion.element, therefore not having a complete PK present (TBD). I would think that there should be a reference back to the parent (element). I then switched back to hydrating my entity objects as normal. I should have loaded all the data into the collections therefore stopping any need to do subsequent DB calls. # Problem/Bug When I access the collection for the versions (e.g. page.elements.elementVersions) the elementVersions are reloaded again from the database. (e.g. A new SQL call is made to the server), even though my first join had loaded the data. I believe that when it is using a FK in the PK composition it is not correctly seeing it has loaded the data already. # Weird Behaviour If I do a DQL that joins the relationship back, I can avoid the database reloading the collection again: SELECT page, element, elementVersion, elementVersionElement FROM page JOIN page.elements AS element JOIN page.elementVersions AS elementVersion JOIN elementVersion.element AS elementVersionElement WHERE page.id = :pageId. By joining the table that is used for the FK/PK scenario back onto itself it prevents another SQL call being made when I attempt to access page.elements.elementVersions. If I switch back to HYDRATE_ARRAY, I can see that now the elementVersions have the element variable, and it appears that this allows it to identify that it has it in the collection and no-longer needs to re-run SQL to locate the object again. This results in unavoidable additional SQL calls for each element that exists on the page (scales proportionate to number of elements). # My Thoughts I am thinking that in the hydrate process it is not setting the FK relationship of elementVersion.element, causing Doctrine to attempt to re-run SQL to obtain the collection again (maybe because it thinks that the objects do not have valid/complete PK). I think somewhere the mapping when it creates the objects is just missing the bit where the proxy gains a value for this property back to the parent.
admin added the Bug label 2026-01-22 13:22:56 +01:00
admin closed this issue 2026-01-22 13:22:56 +01:00
Author
Owner

@doctrinebot commented on GitHub (Sep 4, 2011):

Comment created by cammanderson:

I missed some backwards links between the element and the page.

@doctrinebot commented on GitHub (Sep 4, 2011): Comment created by cammanderson: I missed some backwards links between the element and the page.
Author
Owner

@doctrinebot commented on GitHub (Sep 4, 2011):

Comment created by cammanderson:

I am developing a test case for this issue. Will share github link. thanks

@doctrinebot commented on GitHub (Sep 4, 2011): Comment created by cammanderson: I am developing a test case for this issue. Will share github link. thanks
Author
Owner

@doctrinebot commented on GitHub (Sep 5, 2011):

Comment created by cammanderson:

Realised when I was doing PHP Unit Testing that I was getting some index undefined issues. It was around the generation of Hash values in the ObjectHydrator:217.

It was attempting to look at the $data for the FK element. In my example: undefined index element. By making it look up the associationMappings for the field name element it would be referencing the correct field value.

Updated around lines 217 as follows:

        foreach ($class->identifier as $fieldName) {
            // Add in if the class identifier has data from an associative mapping
            if (isset($class->associationMappings[$fieldName])) {
                $idHash .= $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']];
            } else {
                $idHash .= $data[$fieldName];
            }
        }

Not sure of the practice to submit a pull request. I am assuming I need corresponding test cases?

@doctrinebot commented on GitHub (Sep 5, 2011): Comment created by cammanderson: Realised when I was doing PHP Unit Testing that I was getting some index undefined issues. It was around the generation of Hash values in the ObjectHydrator:217. It was attempting to look at the $data for the FK element. In my example: undefined index element. By making it look up the associationMappings for the field name element it would be referencing the correct field value. Updated around lines 217 as follows: ``` foreach ($class->identifier as $fieldName) { // Add in if the class identifier has data from an associative mapping if (isset($class->associationMappings[$fieldName])) { $idHash .= $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']]; } else { $idHash .= $data[$fieldName]; } } ``` Not sure of the practice to submit a pull request. I am assuming I need corresponding test cases?
Author
Owner

@doctrinebot commented on GitHub (Sep 5, 2011):

Comment created by cammanderson:

Found this was a duplicate issue of DDC-1300.

@doctrinebot commented on GitHub (Sep 5, 2011): Comment created by cammanderson: Found this was a duplicate issue of [DDC-1300](http://www.doctrine-project.org/jira/browse/DDC-1300).
Author
Owner

@doctrinebot commented on GitHub (Sep 5, 2011):

Issue was closed with resolution "Fixed"

@doctrinebot commented on GitHub (Sep 5, 2011): Issue was closed with resolution "Fixed"
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#1707