Using composite key that points to the same entity class leads to memory leaks during flush #7397

Closed
opened 2026-01-22 15:51:12 +01:00 by admin · 1 comment
Owner

Originally created by @smilesrg on GitHub (Jul 17, 2024).

Bug Report

Q A
BC Break no
Version 3.2.1

Summary

Using composite key that points to the same entity class leads to the memory leaks during flush

How to reproduce

There are two given entities, persisting Rate() then flushing leads to the Fatal error: Allowed memory size of... error

<?php declare(strict_types=1);

namespace App\Entity;

use App\Repository\RateRepository;
use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM;

#[ORM\HasLifecycleCallbacks]
#[ORM\Entity(repositoryClass: RateRepository::class)]
class Rate
{
    #[ORM\Id]
    #[ORM\ManyToOne(cascade: ['persist', 'remove'])]
    #[ORM\JoinColumn(name: 'base_currency', referencedColumnName: 'code', nullable: false)]
    private ?Currency $baseCurrency;

    #[ORM\Id]
    #[ORM\ManyToOne(cascade: ['persist', 'remove'])]
    #[ORM\JoinColumn(name: 'target_currency', referencedColumnName: 'code', nullable: false)]
    private ?Currency $targetCurrency;

    #[ORM\Column]
    private ?float $rate;

    #[ORM\Column]
    private ?DateTimeImmutable $lastUpdated = null;

    public function __construct(Currency $baseCurrency, Currency $targetCurrency, float $rate)
    {
        $this->baseCurrency = $baseCurrency;
        $this->targetCurrency = $targetCurrency;
        $this->rate = $rate;
    }

    #[ORM\PreFlush]
    public function preFlush(): void
    {
        $this->lastUpdated = new DateTimeImmutable();
    }

    public function getBaseCurrency(): ?Currency
    {
        return $this->baseCurrency;
    }

    public function getTargetCurrency(): ?Currency
    {
        return $this->targetCurrency;
    }

    public function getRate(): ?float
    {
        return $this->rate;
    }

    public function getLastUpdated(): ?DateTimeImmutable
    {
        return $this->lastUpdated;
    }
}
<?php declare(strict_types=1);

namespace App\Entity;

use App\Repository\CurrencyRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: CurrencyRepository::class)]
class Currency
{
    #[ORM\Id]
    #[ORM\Column(length: 3)]
    private string $code;

    #[ORM\Column(length: 255)]
    private string $name;

    #[ORM\Column(length: 3)]
    private string $symbol;

    public function __construct(string $code, string $name, string $symbol)
    {
        $this->code = $code;
        $this->name = $name;
        $this->symbol = $symbol;
    }

    public function getCode(): string
    {
        return $this->code;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getSymbol(): string
    {
        return $this->symbol;
    }
}
Originally created by @smilesrg on GitHub (Jul 17, 2024). ### Bug Report <!-- Fill in the relevant information below to help triage your issue. --> | Q | A |------------ | ------ | BC Break | no | Version | 3.2.1 #### Summary Using composite key that points to the same entity class leads to the memory leaks during flush #### How to reproduce There are two given entities, persisting `Rate()` then flushing leads to the `Fatal error: Allowed memory size of...` error ```php <?php declare(strict_types=1); namespace App\Entity; use App\Repository\RateRepository; use DateTimeImmutable; use Doctrine\ORM\Mapping as ORM; #[ORM\HasLifecycleCallbacks] #[ORM\Entity(repositoryClass: RateRepository::class)] class Rate { #[ORM\Id] #[ORM\ManyToOne(cascade: ['persist', 'remove'])] #[ORM\JoinColumn(name: 'base_currency', referencedColumnName: 'code', nullable: false)] private ?Currency $baseCurrency; #[ORM\Id] #[ORM\ManyToOne(cascade: ['persist', 'remove'])] #[ORM\JoinColumn(name: 'target_currency', referencedColumnName: 'code', nullable: false)] private ?Currency $targetCurrency; #[ORM\Column] private ?float $rate; #[ORM\Column] private ?DateTimeImmutable $lastUpdated = null; public function __construct(Currency $baseCurrency, Currency $targetCurrency, float $rate) { $this->baseCurrency = $baseCurrency; $this->targetCurrency = $targetCurrency; $this->rate = $rate; } #[ORM\PreFlush] public function preFlush(): void { $this->lastUpdated = new DateTimeImmutable(); } public function getBaseCurrency(): ?Currency { return $this->baseCurrency; } public function getTargetCurrency(): ?Currency { return $this->targetCurrency; } public function getRate(): ?float { return $this->rate; } public function getLastUpdated(): ?DateTimeImmutable { return $this->lastUpdated; } } ``` ```php <?php declare(strict_types=1); namespace App\Entity; use App\Repository\CurrencyRepository; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: CurrencyRepository::class)] class Currency { #[ORM\Id] #[ORM\Column(length: 3)] private string $code; #[ORM\Column(length: 255)] private string $name; #[ORM\Column(length: 3)] private string $symbol; public function __construct(string $code, string $name, string $symbol) { $this->code = $code; $this->name = $name; $this->symbol = $symbol; } public function getCode(): string { return $this->code; } public function getName(): string { return $this->name; } public function getSymbol(): string { return $this->symbol; } } ```
admin closed this issue 2026-01-22 15:51:13 +01:00
Author
Owner

@smilesrg commented on GitHub (Jul 17, 2024):

Closing as invalid

@smilesrg commented on GitHub (Jul 17, 2024): Closing as invalid
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7397