Autor Zpráva
Waren
Profil
Mám ve chybovém logu někdy tohle: Doctrine\ORM\ORMException: The EntityManager is closed

Já tohle určitě nevolám, protože nevím ani proč uzavírat EntityManager. Nejspíše udělám void metodu close, aby se tohle nestávalo. A teď k otázce, jaký to má důvod, máte nějaký příklad proč tohle?
Keeehi
Profil
Waren:
Ono půjde asi o něco jiného. Tam se nepíše, že metoda close neexistuje. Kdyby něco takovou metodu chtělo volat a ona by neexistovala, ta hláška by vypadala úplně jinak.

Tohle se stává, když se třeba nepovedou uložit nějaká data. Například když je nad nějakým sloupcem unikátní index a ty sesnažíš uložit duplikátní hodnotu. V takovém případě se EntityManager "rozbije" a pokud se s ním snažíš dál pracovat, tak hází tyhle exceptiony. Tedy alespoň myslím. Právě kvůli tomuhle uzavírání EM jsem už před dlouhou dobou Doctrine ORM opustil.
Tudíž tvým úkolem je zjistit, při které komunikaci s databází dochází chybě kterou Doctrine nerozdýchá a zajistit, aby k ní nedocházelo.
Waren
Profil
Myslel jsem to tak, že metoda close nebude dělat nic.

Problém dělá přesně tento kód:

        $entry = $this->findByStatusAndNow($status);

        if ($status instanceof Story) {
            $this->storyModel->updateViews($status, $incrementBy);
        }

        if (!$entry) {
            $entry = new StatusView($status, $this->dateTimeFactory->create(), $incrementBy);

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

            try {
                $this->em->flush();

                return;
            } catch (UniqueConstraintViolationException $e) {
                $entry = $this->findByStatusAndNow($status);
                if (!$entry) {
                    return;
                }
            }
        }

        $entry->incrementViews($incrementBy);

        $this->em->merge($entry);
        $this->em->flush();

try, catch UniqueConstraintViolationException, jakmile vyhodí tuto výjimku, tak se em uzavře a už s ním nejde nic dělat.

To try, catch tam imho musí být, protože jiný request může stihnout zapsat dříve, než daný request.

Napadá někoho z vás jak toto přepsat?


Řešení je takovéto, bohužel close nestačí přepsat, protože EntityManager je final a řeší se to dekorátorem

    private function recreateIfClosed(): void {
        if (!$this->isOpen()) {
            $this->wrapped = DoctrineEntityManager::create(
                $this->wrapped->getConnection(), $this->wrapped->getConfiguration(), $this->wrapped->getEventManager()
            );
        }
    }

    public function persist($object) {
        $this->recreateIfClosed();

        parent::persist($object);
    }

    public function remove($object) {
        $this->recreateIfClosed();

        parent::remove($object);
    }

    public function merge($object) {
        $this->recreateIfClosed();

        return parent::merge($object);
    }

    public function refresh($object) {
        $this->recreateIfClosed();

        parent::refresh($object);
    }

    public function flush($entity = null): void {
        parent::flush($entity);
    }

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0