РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
544 of 1361 menu

Исключение OptimisticLockException

Исключение OptimisticLockException выбрасывается Doctrine ORM, когда две транзакции пытаются одновременно изменить одну и ту же сущность. Оно относится к механизму оптимистичной блокировки: версия сущности проверяется при записи, и если она уже была изменена другой транзакцией, возникает конфликт. Исключение помогает обнаружить такие ситуации и корректно обработать их, например, повторив операцию или показав пользователю сообщение об ошибке.

Синтаксис

<?php throw new OptimisticLockException( string $message = '', Throwable $previous = null ); ?>

Пример

Рассмотрим сущность с полем версии:

<?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] class Article { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null; #[ORM\Column(type: 'string')] private string $title; #[ORM\Column(type: 'text')] private string $text; #[ORM\Version] #[ORM\Column(type: 'integer')] private int $version = 1; public function getTitle(): string { return $this->title; } public function setTitle(string $title): void { $this->title = $title; } } ?>

Теперь попробуем сохранить сущность, версия которой устарела. В реальной ситуации это может произойти при параллельной работе двух пользователей. Сымитируем конфликт:

<?php namespace App\Controller; use App\Entity\Article; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\OptimisticLockException; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class ArticleController extends AbstractController { #[Route('/article/update', name: 'article_update')] public function update(EntityManagerInterface $em): Response { $article = $em->find(Article::class, 1); $article->setTitle('abcde'); try { $em->flush(); } catch (OptimisticLockException $e) { return new Response($e->getMessage()); } return new Response('updated'); } } ?>

Если сущность была изменена другой транзакцией, результат выполнения кода будет примерно таким:

"The optimistic lock failed, version 1 was expected, but is actually 2"

Пример

Обработаем исключение и попробуем повторить операцию с актуальной версией сущности:

<?php namespace App\Controller; use App\Entity\Article; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\OptimisticLockException; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class ArticleController extends AbstractController { #[Route('/article/retry', name: 'article_retry')] public function retry(EntityManagerInterface $em): Response { $attempts = 0; while ($attempts < 3) { try { $article = $em->find(Article::class, 1); $article->setTitle('abcde'); $em->flush(); return new Response('updated'); } catch (OptimisticLockException $e) { $attempts++; $em->refresh($article); } } return new Response('conflict'); } } ?>

Результат выполнения кода при успешном повторе:

"updated"

Смотрите также

  • исключение PessimisticLockException,
    которое возникает при пессимистичной блокировке
  • исключение EntityNotFoundException,
    которое выбрасывается, если сущность не найдена
  • исключение UniqueConstraintViolationException,
    которое сигнализирует о нарушении уникальности
  • класс FlattenException,
    который представляет исключение в виде массива
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить