LEFT JOIN results with optional references are being hydrated AND move to managed state #6617

Open
opened 2026-01-22 15:35:46 +01:00 by admin · 2 comments
Owner

Originally created by @boesing on GitHub (Jan 29, 2021).

Hey there,

I dont have a current example but last year, I was tuning some of our code to avoid these "PARTIAL LOAD" queries which are executed when an entity is being fetched from the database.

The only thing I remember is, that we had the following case:

  • table a references table b (but reference is not required to exist) as inversed side
  • table b is owning side of the relation to table a

As the relation is not necessarily required, I am using leftJoin in the Query Builder and add the table b entity to the select clause.

When the query was executed, I've received the hydrated entity for table a with an hydrated entity of table b (containing only null values). As this aint annoying enough, that entity of table b was also considered as managed state in the UnitOfWork.

I am not sure if you guys can follow me but I consider this as a bug.

Any ideas on how I could fix that? I'm willing to create a PR regarding this as I think checking if the primary key of entity B not being null could be an indicator of an existing reference, right?

Originally created by @boesing on GitHub (Jan 29, 2021). Hey there, I dont have a current example but last year, I was tuning some of our code to avoid these "PARTIAL LOAD" queries which are executed when an entity is being fetched from the database. The only thing I remember is, that we had the following case: - table a references table b (but reference is not required to exist) as inversed side - table b is owning side of the relation to table a As the relation is not necessarily required, I am using `leftJoin` in the Query Builder and add the table b entity to the `select` clause. When the query was executed, I've received the hydrated entity for table a with an hydrated entity of table b (containing only `null` values). As this aint annoying enough, that entity of table b was also considered as managed state in the UnitOfWork. I am not sure if you guys can follow me but I consider this as a bug. Any ideas on how I could fix that? I'm willing to create a PR regarding this as I think checking if the primary key of entity B not being null could be an indicator of an existing reference, right?
Author
Owner

@alexpkalinka commented on GitHub (Feb 3, 2021):

Today I experienced exactly the same bug, but weirdly enough it was caused by a typo in the select() clause. I put the same table alias twice in the select() and that table was leftJoin()-ed. Something like this:

$em
    ->getRepository(Parent::class)
    ->createQueryBuilder("p")
    ->leftJoin("p.child", "c")
    ->select("p, c, c")
    ->getQuery()
    ->getResult();

If p.child is NULL then c shouldn't be hydrated. But as @boesing described, the table c was hydrated with nulls instead. And in my case it was even more critical since I have type-hinted fields in the classes, so when Doctrine tried to set non-nullable properties as null PHP crashed with errors like Typed property Child::$name must be string, null used.

However, if you remove the second c then the bug will disappear.

I still think it's a bug in Doctrine, but it seems like it only happens when you put the same table alias twice in the select() statement.

Doctrine ORM version: 2.8.1

@alexpkalinka commented on GitHub (Feb 3, 2021): Today I experienced exactly the same bug, but weirdly enough it was caused by a typo in the `select()` clause. I put the same table alias twice in the `select()` and that table was `leftJoin()`-ed. Something like this: ```php $em ->getRepository(Parent::class) ->createQueryBuilder("p") ->leftJoin("p.child", "c") ->select("p, c, c") ->getQuery() ->getResult(); ``` If `p.child` is `NULL` then `c` shouldn't be hydrated. But as @boesing described, the table `c` was hydrated with `null`s instead. And in my case it was even more critical since I have type-hinted fields in the classes, so when Doctrine tried to set non-nullable properties as `null` PHP crashed with errors like `Typed property Child::$name must be string, null used`. However, if you remove the second `c` then the bug will disappear. I still think it's a bug in Doctrine, but it seems like it only happens when you put the same table alias twice in the `select()` statement. Doctrine ORM version: `2.8.1`
Author
Owner

@mindaugasvcs commented on GitHub (Nov 21, 2023):

I think this might be useful for somebody.
Actually defining entity relations is required for Doctrine to properly hydrate objects in leftJoin when using entity class instead of relation field.
I don't know if it's a bug or intentional but changing CommentReaction::class to 'c.reactions' and definning the relation fixed my issue: https://github.com/doctrine/orm/issues/5595#issuecomment-1818016632

@mindaugasvcs commented on GitHub (Nov 21, 2023): I think this might be useful for somebody. Actually defining entity relations is required for Doctrine to properly hydrate objects in leftJoin when using entity class instead of relation field. I don't know if it's a bug or intentional but changing CommentReaction::class to 'c.reactions' and definning the relation fixed my issue: https://github.com/doctrine/orm/issues/5595#issuecomment-1818016632
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#6617