简体   繁体   中英

[Symfony][Doctrine] Batch Processing - Bulk inserts with ManyToOne relation = ERROR: A new entity was found through the relationship

I have 2 entities with ManyToOne relationship: Playlist and PlaylistVideo. One Playlist can have many videos. PlaylistVideo belongs to Playlist. Playlist already exists in database.

I am trying to use Bulk inserts, but i get:

A new entity was found through the relationship 'App\Entity\Playlist\PlaylistVideo#playlist' that was not configured to cascade persist operations for entity: App\Entity\Playlist\Playlist__1. 
To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).

Playlist entity:

class Playlist
{
    /**
     * @ORM\OneToMany(targetEntity=PlaylistVideo::class, mappedBy="playlist")
     * @Groups({"playlist"})
     */
    private Collection $videos;

    ...

    public function addVideo(PlaylistVideo $video): self
    {
        if (!$this->videos->contains($video)) {
            $this->videos[] = $video;
            $video->setPlaylist($this);
        }

        return $this;
    }

PlaylistVideo entity:

class PlaylistVideo
{
    /**
     * @ORM\ManyToOne(targetEntity=Playlist::class, inversedBy="videos")
     * @ORM\JoinColumn(nullable=false)
     */
    private Playlist $playlist;

    ...

    public function setPlaylist(Playlist $playlist): self
    {
        $this->playlist = $playlist;

        return $this;
    }

Batch Processing - Bulk Inserts:

    /**
     * Batch Processing - Bulk Inserts
     * @param VideoDto[] $videos
     */
    public function bulkInserts(Playlist $playlist, array $videos)
    {
        $this->em->getConnection()->getConfiguration()->setSQLLogger(null);

        $videosAmount = count($videos);
        $batchSize = 50;
        for ($i = 0; $i < $videosAmount; $i++) {
            $video = $videos[$i];

            $playlistVideo = (new PlaylistVideo())
                ->setPlaylist($playlist)
                ->setVideoId($video->id)
                ->setTitle($video->title);

            $this->em->persist($playlistVideo);

            if (($i % $batchSize) === 0) {
                $this->em->flush();
                $this->em->clear();
            }
        }

        $this->em->flush();
        $this->em->clear();
    }

I cant add cascade={"persist"} (in PlaylistVideo @ORM\ManyToOne() ) because i don't want end up with many Playlists.

I have tried everything, but i can't just add videos to playlist.

You call $this->em->clear(); and use the same Playlist entity after it. The EntityManager does not know it anymore. You need to reload it.

for ($i = 0; $i < $videosAmount; $i++) {
    $video = $videos[$i];

    $playlistVideo = (new PlaylistVideo())
        ->setPlaylist($playlist)
        ->setVideoId($video->id)
        ->setTitle($video->title);

    $this->em->persist($playlistVideo);

    if (($i % $batchSize) === 0) {
        $this->em->flush();
        $this->em->clear();

        // Reload the Playlist entity after clearing the EntityManager
        $playlist = $this->em->getRepository(Playlist::class)->find($playlist->getId());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM