BasicEntityPersister & Composite keys #6466

Open
opened 2026-01-22 15:33:42 +01:00 by admin · 7 comments
Owner

Originally created by @tasselchof on GitHub (May 14, 2020).

I have an entity, which is linked to itself:

Offer {
/**
     * @var int
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     * @ORM\Column(type="bigint")
     */
    protected $id;
    /**
     * @var Shop
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     * @ORM\ManyToOne(targetEntity="Products\Entity\Shop")
     * @ORM\JoinColumn(name="shop_id", referencedColumnName="id")
     */
    protected $shop;
/**
     * @var Offer
     * @ORM\ManyToOne(targetEntity="Products\Entity\Product\Offer", fetch="EXTRA_LAZY")
     * @ORM\JoinColumns({
     *     @ORM\JoinColumn(name="parent_id", referencedColumnName="id"),
     *     @ORM\JoinColumn(name="shop_id", referencedColumnName="shop_id")
     * })
     */
    protected $parent;
}
}

This entity has a composite key and as long as I have the second link in parent and parent = null, basic entity persister in function \Doctrine\ORM\Persisters\Entity\BasicEntityPersister::prepareUpdateData setting shop in main entity to null.

Little debug on the issue (I was checking how it is parsing each key inside prepareUpdateData):

!!!!!!!!!!!!!!!!!shop+++++++++++++++++Array
(
[products_product_offers] => Array
(
[id] => 1043186
[article] =>
[name] => Test
[type] => simple
[image] =>
[barcodes] => Array
(
)

        [sku] => 
        [dimensions] => 
        [weight] => 
        [purchasingPrice] => 3
        [price] => 
        [state] => normal
        [created] => DateTime Object
            (
                [date] => 2020-05-14 23:01:00.355523
                [timezone_type] => 3
                [timezone] => UTC
            )

        [updated] => DateTime Object
            (
                [date] => 2020-05-14 23:01:00.355527
                [timezone_type] => 3
                [timezone] => UTC
            )

        [extId] => ext
        [raw] => 
        [eav] => 
        [doc] => 
        [docUpdated] => 
        [shop_id] => 521
    )

)
!!!!!!!!!!!!!!!!!parent+++++++++++++++++Array
(
[products_product_offers] => Array
(
[id] => 1043186
[article] =>
[name] => Test
[type] => simple
[image] =>
[barcodes] => Array
(
)

        [sku] => 
        [dimensions] => 
        [weight] => 
        [purchasingPrice] => 3
        [price] => 
        [state] => normal
        [created] => DateTime Object
            (
                [date] => 2020-05-14 23:01:00.355523
                [timezone_type] => 3
                [timezone] => UTC
            )

        [updated] => DateTime Object
            (
                [date] => 2020-05-14 23:01:00.355527
                [timezone_type] => 3
                [timezone] => UTC
            )

        [extId] => ext
        [raw] => 
        [eav] => 
        [doc] => 
        [docUpdated] => 
        [shop_id] =>
        [parent_id] => 
    )

)
!!!!!!!!!!!!!!!!!currency+++++++++++++++++Array
(
[products_product_offers] => Array
(
[id] => 1043186
[article] =>
[name] => Test
[type] => simple
[image] =>
[barcodes] => Array
(
)

        [sku] => 
        [dimensions] => 
        [weight] => 
        [purchasingPrice] => 3
        [price] => 
        [state] => normal
        [created] => DateTime Object
            (
                [date] => 2020-05-14 23:01:00.355523
                [timezone_type] => 3
                [timezone] => UTC
            )

        [updated] => DateTime Object
            (
                [date] => 2020-05-14 23:01:00.355527
                [timezone_type] => 3
                [timezone] => UTC
            )

        [extId] => ext
        [raw] => 
        [eav] => 
        [doc] => 
        [docUpdated] => 
        [shop_id] =>
        [parent_id] => 
        [currency_id] => 
    )

)

Originally created by @tasselchof on GitHub (May 14, 2020). I have an entity, which is linked to itself: ``` Offer { /** * @var int * @ORM\Id * @ORM\GeneratedValue(strategy="NONE") * @ORM\Column(type="bigint") */ protected $id; /** * @var Shop * @ORM\Id * @ORM\GeneratedValue(strategy="NONE") * @ORM\ManyToOne(targetEntity="Products\Entity\Shop") * @ORM\JoinColumn(name="shop_id", referencedColumnName="id") */ protected $shop; /** * @var Offer * @ORM\ManyToOne(targetEntity="Products\Entity\Product\Offer", fetch="EXTRA_LAZY") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="parent_id", referencedColumnName="id"), * @ORM\JoinColumn(name="shop_id", referencedColumnName="shop_id") * }) */ protected $parent; } } ``` This entity has a composite key and as long as I have the second link in parent and parent = null, basic entity persister in function \Doctrine\ORM\Persisters\Entity\BasicEntityPersister::prepareUpdateData setting shop in main entity to null. Little debug on the issue (I was checking how it is parsing each key inside prepareUpdateData): !!!!!!!!!!!!!!!!!shop+++++++++++++++++Array ( [products_product_offers] => Array ( [id] => 1043186 [article] => [name] => Test [type] => simple [image] => [barcodes] => Array ( ) [sku] => [dimensions] => [weight] => [purchasingPrice] => 3 [price] => [state] => normal [created] => DateTime Object ( [date] => 2020-05-14 23:01:00.355523 [timezone_type] => 3 [timezone] => UTC ) [updated] => DateTime Object ( [date] => 2020-05-14 23:01:00.355527 [timezone_type] => 3 [timezone] => UTC ) [extId] => ext [raw] => [eav] => [doc] => [docUpdated] => [shop_id] => 521 ) ) !!!!!!!!!!!!!!!!!parent+++++++++++++++++Array ( [products_product_offers] => Array ( [id] => 1043186 [article] => [name] => Test [type] => simple [image] => [barcodes] => Array ( ) [sku] => [dimensions] => [weight] => [purchasingPrice] => 3 [price] => [state] => normal [created] => DateTime Object ( [date] => 2020-05-14 23:01:00.355523 [timezone_type] => 3 [timezone] => UTC ) [updated] => DateTime Object ( [date] => 2020-05-14 23:01:00.355527 [timezone_type] => 3 [timezone] => UTC ) [extId] => ext [raw] => [eav] => [doc] => [docUpdated] => [shop_id] => [parent_id] => ) ) !!!!!!!!!!!!!!!!!currency+++++++++++++++++Array ( [products_product_offers] => Array ( [id] => 1043186 [article] => [name] => Test [type] => simple [image] => [barcodes] => Array ( ) [sku] => [dimensions] => [weight] => [purchasingPrice] => 3 [price] => [state] => normal [created] => DateTime Object ( [date] => 2020-05-14 23:01:00.355523 [timezone_type] => 3 [timezone] => UTC ) [updated] => DateTime Object ( [date] => 2020-05-14 23:01:00.355527 [timezone_type] => 3 [timezone] => UTC ) [extId] => ext [raw] => [eav] => [doc] => [docUpdated] => [shop_id] => [parent_id] => [currency_id] => ) )
Author
Owner

@tasselchof commented on GitHub (May 20, 2020):

850d57e791/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php (L667)

Here, when BasicEntityPersister iterating through fields it's rewriting shop_id (value is correct at the first step, on the second it's rewriting it because of the composite key).

@tasselchof commented on GitHub (May 20, 2020): https://github.com/doctrine/orm/blob/850d57e7912573522c556216afa756aed16696d1/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php#L667 Here, when BasicEntityPersister iterating through fields it's rewriting shop_id (value is correct at the first step, on the second it's rewriting it because of the composite key).
Author
Owner

@stakahashi commented on GitHub (May 27, 2020):

+1

@stakahashi commented on GitHub (May 27, 2020): +1
Author
Owner

@beberlei commented on GitHub (May 27, 2020):

Two times the same join column looks quite dangerous to me. I am not sure that Doctrine can handle this internally.

@beberlei commented on GitHub (May 27, 2020): Two times the same join column looks quite dangerous to me. I am not sure that Doctrine can handle this internally.
Author
Owner

@tasselchof commented on GitHub (May 27, 2020):

There is no double join, it is one join with a composite key. We updated entity adding field "parent shop" and this is solved an issue. Generally, we just don't use this field in any selects (also, we are not using doctrine there anymore - we refactored this API to use native SQL).

@tasselchof commented on GitHub (May 27, 2020): There is no double join, it is one join with a composite key. We updated entity adding field "parent shop" and this is solved an issue. Generally, we just don't use this field in any selects (also, we are not using doctrine there anymore - we refactored this API to use native SQL).
Author
Owner

@tasselchof commented on GitHub (May 27, 2020):

I am not sure that Doctrine can handle this internally.

It can - this version (I am not sure, maybe 3.0 handling it) just don't have a check where the field is related to - to entity itself or to related. And if there is no parent inside cycle it is nullifying the main entity value (because an entity doesn't have parent).

It is written in docs, that Doctrine is supporting composite keys natively. It does support them. But there are limits.

I believe there should be an exception in this situation or property should be handled appropriate way =)

@tasselchof commented on GitHub (May 27, 2020): > I am not sure that Doctrine can handle this internally. It can - this version (I am not sure, maybe 3.0 handling it) just don't have a check where the field is related to - to entity itself or to related. And if there is no parent inside cycle it is nullifying the main entity value (because an entity doesn't have parent). It is written in docs, that Doctrine is supporting composite keys natively. It does support them. But there are limits. I believe there should be an exception in this situation or property should be handled appropriate way =)
Author
Owner

@beberlei commented on GitHub (May 27, 2020):

I don't understand, you are saying it can or it cannot handle it both in the same sentence.

@beberlei commented on GitHub (May 27, 2020): I don't understand, you are saying it can or it cannot handle it both in the same sentence.
Author
Owner

@tasselchof commented on GitHub (May 27, 2020):

I mean that it potentially can handle this relation, but because of this issue it is not handling it an appropriate way.

@tasselchof commented on GitHub (May 27, 2020): I mean that it potentially can handle this relation, but because of this issue it is not handling it an appropriate way.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#6466