Last active
May 2, 2018 19:21
-
-
Save dmz9/1a93b354c025aec3e00042cae745e8af to your computer and use it in GitHub Desktop.
Sequence per entity for doctrine with pessimistic lock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class BusinessTransactionHandler{ | |
public function persistOrder( Order $order, EntityManager $em ) { | |
$em->beginTransaction(); | |
try { | |
$counter = $em->find( "AppBundle:ShopOrderCounter", | |
$order->getShop() | |
->getOrderCounter() | |
->getId(), | |
LockMode::PESSIMISTIC_WRITE ); | |
} catch ( OptimisticLockException $e ) { | |
throw new HandlerException( "Ошибка блокировки", $e ); | |
} catch ( TransactionRequiredException $e ) { | |
throw new HandlerException( "Ошибка блокировки", $e ); | |
} catch ( ORMException $e ) { | |
throw new HandlerException( "Ошибка блокировки", $e ); | |
} | |
$order->setNumber( $counter->nextNumber() ); | |
$em->persist( $order ); | |
try { | |
$em->flush(); | |
$em->commit(); | |
} /** @noinspection PhpRedundantCatchClauseInspection */ catch ( UniqueConstraintViolationException $unique ) { | |
$em->rollback(); | |
throw new ConflictHttpException( "Такой заказ уже существует", $unique ); | |
} catch ( \Exception $exception ) { | |
$em->rollback(); | |
throw new BadRequestHttpException( "Ошибка сервера при записи данных заказа", $exception ); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Entity; | |
use Doctrine\Common\Collections\ArrayCollection; | |
use Doctrine\Common\Collections\Collection; | |
use Doctrine\ORM\Mapping as ORM; | |
/** | |
* Shop | |
* | |
* @ORM\Table(name="shop") | |
* @ORM\Entity(repositoryClass="AppBundle\Repository\ShopRepository") | |
*/ | |
class Shop { | |
/** | |
* @var int | |
* | |
* @ORM\Column(name="id", type="integer") | |
* @ORM\Id | |
* @ORM\GeneratedValue(strategy="IDENTITY") | |
*/ | |
private $id; | |
/** | |
* @var ArrayCollection | |
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Order", mappedBy="shop") | |
*/ | |
private $orders; | |
/** | |
* @var ShopOrderCounter | |
* @ORM\OneToOne(targetEntity="ShopOrderCounter", cascade={"all"}) | |
* @ORM\JoinColumn(name="order_counter", referencedColumnName="id") | |
*/ | |
protected $orderCounter; | |
/** | |
* @return ShopOrderCounter | |
*/ | |
public function getOrderCounter() { | |
return $this->orderCounter; | |
} | |
/** | |
* Shop constructor. | |
*/ | |
public function __construct() { | |
$this->orders = new ArrayCollection(); | |
$this->orderCounter = new ShopOrderCounter(); | |
} | |
/** | |
* @return int | |
*/ | |
public function getId() { | |
return $this->id; | |
} | |
public function registerOrder( Order $order ) { | |
if ( ! $this->orders->contains( $order ) ) { | |
$this->orders->add( $order ); | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Entity; | |
use Doctrine\ORM\Mapping as ORM; | |
/** | |
* ShopNumber | |
* | |
* @ORM\Table(name="shop_order_counter") | |
* @ORM\Entity(repositoryClass="AppBundle\Repository\ShopOrderCounterRepository") | |
*/ | |
class ShopOrderCounter { | |
/** | |
* @var int | |
* | |
* @ORM\Column(name="id", type="integer") | |
* @ORM\Id | |
* @ORM\GeneratedValue(strategy="IDENTITY") | |
*/ | |
protected $id; | |
/** | |
* @var int следующий свободный номер заказа | |
* @ORM\Column(name="next_order_number", type="integer") | |
*/ | |
protected $nextOrderNumber; | |
/** | |
* ShopNumber constructor. | |
* | |
* @param int $nextOrderNumber | |
*/ | |
public function __construct() { | |
$this->nextOrderNumber = 1; | |
} | |
/** | |
* Get id | |
* | |
* @return int | |
*/ | |
public function getId() { | |
return $this->id; | |
} | |
/** | |
* @return int | |
*/ | |
public function nextNumber() { | |
$next = $this->nextOrderNumber; | |
$this->nextOrderNumber = $next + 1; | |
return $next; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment