BC break in one-to-many relationship loading when using binary UUID (or custom) data type #7258

Closed
opened 2026-01-22 15:48:22 +01:00 by admin · 11 comments
Owner

Originally created by @sips-richard on GitHub (Nov 27, 2023).

BC Break Report

Q A
BC Break yes
Version 2.17.0

Summary

One of our micro-services exclusively uses binary UUIDs for all primary keys, using Ramsey's binary UUID data type. When using entity proxy method to fetch eager-loaded collection the UUID objects representing the primary keys are not appropriately converted with the configured data type and are instead implicitly converted to strings, such that when executeQuery in loadAll (called by eagerLoadCollections) is run, the array of IDs in $params are string UUIDs and not the expected binary UUIDs. This causes no entities to be loaded in the collection.

I've had a dig through the code and as far as I can tell expandParameters is resolving the types (correctly) to 102 (array of strings), but not performing any type-specific conversion of values, and simply stringifying the UUID objects.

Previous behavior

Prior to 2.17.0 the collection of related entities was correctly loaded.

Current behavior

Subsequent to the 2.17.0 changes the related entities are not loaded. See summary.

How to reproduce

Implement One-To-Many relationship using BinaryUuid data type (ramsey/uuid-doctrine).

Originally created by @sips-richard on GitHub (Nov 27, 2023). ### BC Break Report | Q | A |------------ | ------ | BC Break | yes | Version | 2.17.0 #### Summary One of our micro-services exclusively uses binary UUIDs for all primary keys, using Ramsey's binary UUID data type. When using entity proxy method to fetch eager-loaded collection the UUID objects representing the primary keys are not appropriately converted with the configured data type and are instead implicitly converted to strings, such that when `executeQuery` in `loadAll` (called by `eagerLoadCollections`) is run, the array of IDs in `$params` are *string* UUIDs and not the expected binary UUIDs. This causes no entities to be loaded in the collection. I've had a dig through the code and as far as I can tell `expandParameters` is resolving the types (correctly) to `102` (array of strings), but not performing any type-specific conversion of values, and simply stringifying the UUID objects. #### Previous behavior Prior to 2.17.0 the collection of related entities was correctly loaded. #### Current behavior Subsequent to the 2.17.0 changes the related entities are not loaded. See summary. #### How to reproduce Implement One-To-Many relationship using BinaryUuid data type (`ramsey/uuid-doctrine`).
admin added the BugBC Break labels 2026-01-22 15:48:22 +01:00
admin closed this issue 2026-01-22 15:48:22 +01:00
Author
Owner

@jennevdmeer commented on GitHub (Nov 28, 2023):

I think I have the same issue using Symfony's uid Ulid as id's for related entry in my SF app. This was working on the 2.16.2 version.

#[ORM\OneToMany(mappedBy: 'chapter', targetEntity: TopicRestartReference::class, cascade: ['all'], fetch: 'EAGER')]
public Collection $topicRestartReferences;
class TopicRestartReference
{
    #[ORM\Id]
    #[ORM\Column(type: 'ulid')]
    #[ORM\GeneratedValue(strategy: 'NONE')]
    public Ulid $id;
@jennevdmeer commented on GitHub (Nov 28, 2023): I think I have the same issue using Symfony's uid `Ulid` as id's for related entry in my SF app. This was working on the 2.16.2 version. ```php #[ORM\OneToMany(mappedBy: 'chapter', targetEntity: TopicRestartReference::class, cascade: ['all'], fetch: 'EAGER')] public Collection $topicRestartReferences; ``` ```php class TopicRestartReference { #[ORM\Id] #[ORM\Column(type: 'ulid')] #[ORM\GeneratedValue(strategy: 'NONE')] public Ulid $id; ```
Author
Owner

@dbannik commented on GitHub (Nov 28, 2023):

@jennevdmeer please remove "fetch=EAGER" and reproduce the problem
maybe the problem is similar to this one https://github.com/doctrine/orm/issues/11091

@dbannik commented on GitHub (Nov 28, 2023): @jennevdmeer please remove "fetch=EAGER" and reproduce the problem maybe the problem is similar to this one https://github.com/doctrine/orm/issues/11091
Author
Owner

@frankverhoeven commented on GitHub (Nov 29, 2023):

Experiencing the same issue, and can indeed confirm that it is related to eager fetching a relation.
When removing the eager loading, the issue is gone.

@frankverhoeven commented on GitHub (Nov 29, 2023): Experiencing the same issue, and can indeed confirm that it is related to eager fetching a relation. When removing the eager loading, the issue is gone.
Author
Owner

@jennevdmeer commented on GitHub (Nov 29, 2023):

@jennevdmeer please remove "fetch=EAGER" and reproduce the problem maybe the problem is similar to this one #11091

Well yes if I remove it they resolve one by one and it "works". Idk all these technical details seems like its the about the same thing? Regardless I'm not getting an error message as you described, my collections are just empty when having eager loading on (as was working before).

@jennevdmeer commented on GitHub (Nov 29, 2023): > @jennevdmeer please remove "fetch=EAGER" and reproduce the problem maybe the problem is similar to this one #11091 Well yes if I remove it they resolve one by one and it "works". Idk all these technical details seems like its the about the same thing? Regardless I'm not getting an error message as you described, my collections are just empty when having eager loading on (as was working before).
Author
Owner

@beberlei commented on GitHub (Nov 30, 2023):

This needs to be fixed indeed, probably did not come up with the test suite as we don't test with the UUID type or similar things a lot

@beberlei commented on GitHub (Nov 30, 2023): This needs to be fixed indeed, probably did not come up with the test suite as we don't test with the UUID type or similar things a lot
Author
Owner

@aguerre commented on GitHub (Feb 8, 2024):

Any update ? Is it fixed or planned to be fixed in 3.0.0 or 2.18.0 ? I see the 2.17.x milestones for this issue but it's seems to be delayed regularly, so i'm wondering if i can update to 2.18.0 nor 3.0.0 directly

@aguerre commented on GitHub (Feb 8, 2024): Any update ? Is it fixed or planned to be fixed in 3.0.0 or 2.18.0 ? I see the 2.17.x milestones for this issue but it's seems to be delayed regularly, so i'm wondering if i can update to 2.18.0 nor 3.0.0 directly
Author
Owner

@ghost commented on GitHub (Mar 13, 2024):

I'm having this issue too. doctrine/orm 2.16.3 is the last version where I was unable to reproduce the issue.

I tried various releases since, all of which reproduce the issue:

2.16.3 working
2.17.0 broken
2.17.5 broken
2.18.3 broken
2.19.0 broken
3.0.3  broken
3.1.0  broken
@ghost commented on GitHub (Mar 13, 2024): I'm having this issue too. doctrine/orm 2.16.3 is the last version where I was unable to reproduce the issue. I tried various releases since, all of which reproduce the issue: ``` 2.16.3 working 2.17.0 broken 2.17.5 broken 2.18.3 broken 2.19.0 broken 3.0.3 broken 3.1.0 broken ```
Author
Owner

@derrabus commented on GitHub (Mar 14, 2024):

Any update ? Is it fixed or planned to be fixed in 3.0.0 or 2.18.0 ?

This is fixed when someone fixes it. Could be you?

@derrabus commented on GitHub (Mar 14, 2024): > Any update ? Is it fixed or planned to be fixed in 3.0.0 or 2.18.0 ? This is fixed when someone fixes it. Could be you?
Author
Owner

@BonBonSlick commented on GitHub (Mar 25, 2024):

I have

Doctrine\ORM\Mapping\ClassMetadata::getIdentifierValues(): Argument #1 ($entity) must be of type object, null given, called in /var/www/hint_api/vendor/doctrine/orm/src/UnitOfWork.php on line 2665

<entity name="App\Domain\Core\Model\AbstractAnimeComponent"
         inheritance-type="JOINED"
 >
 
 // discriminator columns and types ...
 
<one-to-many target-entity="App\Domain\Core\Model\AnimeComponentTranslation"
                  mapped-by="translatedModel"
                  field="translations"
                  orphan-removal="true"
                  index-by="id.uuid"   //  Symfony UUID, manually generated causing crash
                  fetch="EAGER" <<<< --------REMOVING EAGER, which is required by design, REMOVES ERROR
     >
     <cascade>
             <cascade-persist/>
         </cascade>
         <order-by>
             <order-by-field name="translatedField.name"
                             direction="DESC"
             />
             <order-by-field name="translatedField.value"
                             direction="DESC"
             />
         </order-by>
     </one-to-many>
<entity name="App\Domain\Core\Model\AnimeComponentTranslation">

        <!-- Many To One -->
        <many-to-one target-entity="App\Domain\Core\Model\AbstractAnimeComponent"
                     field="translatedModel"
                     inversed-by="translations"
                     fetch="EXTRA_LAZY"
        >
            <join-column name="abstract_anime_component_uuid"
                         referenced-column-name="uuid"
                         on-delete="CASCADE"
                         nullable="false"
            />
        </many-to-one>

    </entity>
    "beberlei/doctrineextensions": "^v1.2.8",
    "doctrine/collections": "^2.2.1",
    "doctrine/common": "^3.3.0",
    "doctrine/dbal": "^4.0",
    "doctrine/doctrine-bundle": "^2.12.0",
    "doctrine/doctrine-migrations-bundle": "^3.3.0",
    "doctrine/orm": "^3.1.0",  <<<< --- ERROR OCCURED AFTER UPGRADE
    "happyr/doctrine-specification": "^v0.8.1",

and I can verify messages above, 2.16 has no this issue.

Component is abstract class used as intermediate entitiy with inheritance type JOINED.
New ORM version crashes, downgrading solves error.

Error is caused inside vendor/doctrine/orm/src/Internal/Hydration/ObjectHydrator.php::138

Very likely the reason for that this BUG https://github.com/doctrine/orm/issues/11091

ThisImportant note, App\Domain\Core\Model\AbstractAnimeComponent is abstract class and we set up relation with non abstract class.
We have similar relations between NON abstract classes, and it seems to work fine:

<entity name="App\Domain\AccessControlListPack\Permission\Model\RolePermissionTranslation">

        <!-- Many To One -->
        <many-to-one target-entity="App\Domain\AccessControlListPack\Permission\Model\RolePermission"
                     field="translatedModel"
                     inversed-by="translations"
                     fetch="EAGER"
        >
            <join-column name="permission_uuid"
                         referenced-column-name="uuid"
                         on-delete="CASCADE"
                         nullable="false"
            />
        </many-to-one>
    </entity>
    <entity name="App\Domain\AccessControlListPack\Permission\Model\RolePermission"
            repository-class="App\Infrastructure\Persistence\Repository\DB\DQL\RolePermission\DQLRepositoryRolePermission"
    >
 <one-to-many target-entity="App\Domain\AccessControlListPack\Permission\Model\RolePermissionTranslation"
                     mapped-by="translatedModel"
                     field="translations"
                     orphan-removal="true"
                     index-by="id.uuid"
                     fetch="EAGER"
        >
            доктрины-->
            <cascade>
                <cascade-persist/>
            </cascade>
        </one-to-many>

So very probably it is somehow related how ORM works with inheritance structure. entities, abstract classes

@BonBonSlick commented on GitHub (Mar 25, 2024): I have **Doctrine\ORM\Mapping\ClassMetadata::getIdentifierValues(): Argument #1 ($entity) must be of type object, null given, called in /var/www/hint_api/vendor/doctrine/orm/src/UnitOfWork.php on line 2665** ``` <entity name="App\Domain\Core\Model\AbstractAnimeComponent" inheritance-type="JOINED" > // discriminator columns and types ... <one-to-many target-entity="App\Domain\Core\Model\AnimeComponentTranslation" mapped-by="translatedModel" field="translations" orphan-removal="true" index-by="id.uuid" // Symfony UUID, manually generated causing crash fetch="EAGER" <<<< --------REMOVING EAGER, which is required by design, REMOVES ERROR > <cascade> <cascade-persist/> </cascade> <order-by> <order-by-field name="translatedField.name" direction="DESC" /> <order-by-field name="translatedField.value" direction="DESC" /> </order-by> </one-to-many> ``` ``` <entity name="App\Domain\Core\Model\AnimeComponentTranslation"> <!-- Many To One --> <many-to-one target-entity="App\Domain\Core\Model\AbstractAnimeComponent" field="translatedModel" inversed-by="translations" fetch="EXTRA_LAZY" > <join-column name="abstract_anime_component_uuid" referenced-column-name="uuid" on-delete="CASCADE" nullable="false" /> </many-to-one> </entity> ``` ``` "beberlei/doctrineextensions": "^v1.2.8", "doctrine/collections": "^2.2.1", "doctrine/common": "^3.3.0", "doctrine/dbal": "^4.0", "doctrine/doctrine-bundle": "^2.12.0", "doctrine/doctrine-migrations-bundle": "^3.3.0", "doctrine/orm": "^3.1.0", <<<< --- ERROR OCCURED AFTER UPGRADE "happyr/doctrine-specification": "^v0.8.1", ``` and I can verify messages above, **2.16 has no this issue.** Component is abstract class used as intermediate entitiy with inheritance type JOINED. New ORM version crashes, downgrading solves error. Error is caused inside vendor/doctrine/orm/src/Internal/Hydration/ObjectHydrator.php::138 Very likely the reason for that this **BUG** https://github.com/doctrine/orm/issues/11091 ThisImportant note, App\Domain\Core\Model\AbstractAnimeComponent is abstract class and we set up relation with non abstract class. We have similar relations between NON abstract classes, and it seems to work fine: ``` <entity name="App\Domain\AccessControlListPack\Permission\Model\RolePermissionTranslation"> <!-- Many To One --> <many-to-one target-entity="App\Domain\AccessControlListPack\Permission\Model\RolePermission" field="translatedModel" inversed-by="translations" fetch="EAGER" > <join-column name="permission_uuid" referenced-column-name="uuid" on-delete="CASCADE" nullable="false" /> </many-to-one> </entity> ``` ``` <entity name="App\Domain\AccessControlListPack\Permission\Model\RolePermission" repository-class="App\Infrastructure\Persistence\Repository\DB\DQL\RolePermission\DQLRepositoryRolePermission" > <one-to-many target-entity="App\Domain\AccessControlListPack\Permission\Model\RolePermissionTranslation" mapped-by="translatedModel" field="translations" orphan-removal="true" index-by="id.uuid" fetch="EAGER" > доктрины--> <cascade> <cascade-persist/> </cascade> </one-to-many> ``` So very probably it is somehow related how ORM works with inheritance structure. entities, abstract classes
Author
Owner

@ghost commented on GitHub (Mar 25, 2024):

@BonBonSlick Which patch version of doctrine/orm 3.1 are you using? In my testing, 3.1.0 is broken but 3.1.1 was fixed.

Here's my latest testing of #11091 for the latest of each minor version branch:

2.16.3      working
2.17.0      broken (EOL I think)
2.17.5      broken (EOL I think)
2.18.3      broken (EOL I think)
2.19.3      working (fixed in 2.19.1)
2.20.x-dev  working
3.0.3       broken
3.1.1       working (fixed in 3.1.1)
3.2.x-dev   working
@ghost commented on GitHub (Mar 25, 2024): @BonBonSlick Which patch version of doctrine/orm 3.1 are you using? In my testing, 3.1.0 is broken but 3.1.1 was fixed. Here's my latest testing of #11091 for the latest of each minor version branch: ``` 2.16.3 working 2.17.0 broken (EOL I think) 2.17.5 broken (EOL I think) 2.18.3 broken (EOL I think) 2.19.3 working (fixed in 2.19.1) 2.20.x-dev working 3.0.3 broken 3.1.1 working (fixed in 3.1.1) 3.2.x-dev working ```
Author
Owner

@BonBonSlick commented on GitHub (Mar 26, 2024):

@amacrobert-meq yes, you were right 3.1.1 works fine, awesome!
Thanks!

@BonBonSlick Which patch version of doctrine/orm 3.1 are you using? In my testing, 3.1.0 is broken but 3.1.1 was fixed.

Here's my latest testing of #11091 for the latest of each minor version branch:

2.16.3      working
2.17.0      broken (EOL I think)
2.17.5      broken (EOL I think)
2.18.3      broken (EOL I think)
2.19.3      working (fixed in 2.19.1)
2.20.x-dev  working
3.0.3       broken
3.1.1       working (fixed in 3.1.1)
3.2.x-dev   working
    "doctrine/orm": "^3.1.0", <<< ---- BROKEN
@BonBonSlick commented on GitHub (Mar 26, 2024): @amacrobert-meq yes, you were right 3.1.1 works fine, awesome! Thanks! > @BonBonSlick Which patch version of doctrine/orm 3.1 are you using? In my testing, 3.1.0 is broken but 3.1.1 was fixed. > > Here's my latest testing of #11091 for the latest of each minor version branch: > > ``` > 2.16.3 working > 2.17.0 broken (EOL I think) > 2.17.5 broken (EOL I think) > 2.18.3 broken (EOL I think) > 2.19.3 working (fixed in 2.19.1) > 2.20.x-dev working > 3.0.3 broken > 3.1.1 working (fixed in 3.1.1) > 3.2.x-dev working > ``` ``` "doctrine/orm": "^3.1.0", <<< ---- BROKEN ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7258