2016-11-11 70 views
0

我在symfony2中有一个文档管理系统。 一旦用户建立了我的文档实体,它将被分配一个序列号。symfony2如何保证序列号未被使用

这是我如何找到要分配的序列号 1)检查数据库中最高使用的序列号 2)分配它并刷新实体。

我使用此序列作为此实体的多个版本的标识符,因此它不是DB的唯一标识符。

如何保证指定的号码是真正独特的?我会锁定在平坦的PHP表,但不知道如何或如果它是symfony2中的最佳做法。

/** 
* Establishes a analysi entity. 
* 
*/ 
public function establishAction(Request $request, Analysis $analysi) 
{ 

    ... 

    $analysi->setSerial($this->getNewSerial());//set a new serial number 
    //TODO: How to confirm this is really not in use since there is no transaction locking going on here? 
    $em->flush($analysi); 

    ... 

} 


private function getNewSerial() 
{    
    $em = $this->getDoctrine()->getManager(); 

    //get highest serial nb from established analysises 
    $results = $em->createQuery("SELECT MAX(a.serial) FROM HazardlogBundle:Analysis a WHERE a.currentVersion = true")->getResult(); 
    $temp = $results[0]; 
    $max_serial = $temp[1]; 

    $new_serial = $max_serial + 1; 

    return $new_serial; 
} 

---------------- UPDATE

我显然必须clearify: 我可以有...

entity A with serial 123 and version 1 
entity B with serial 123 and version 2 
entity C with serial 124 and version 1 
entity D with serial 125 and version 1 

我是什么害怕的是用户同时创建实体C和D,因此我的控制器可以获取用于创建实体C的当前最高序列号,并且在实体C被刷新到DB之前,为用户创建实体D服务的线程将读取最高编号为123的实体C在串行124之前写入数据库。因此,我将最终与实体C & D都有序列124.

也许我可以定义一个唯一的索引,包括串行和版本号一起回避这个问题?

+0

看看学说锁表支持: HTTP://文档。 doctrine-project.org/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency。html#locking-support – erwan

回答

0

我发现了一种由两列组合这样创建唯一索引:

/** 
* Analysis 
* 
* @ORM\Table(name="analysis",uniqueConstraints={@ORM\UniqueConstraint(name="unique_version_serial", columns={"Version", "serial"})}) 
* @ORM\Entity(repositoryClass="HazardlogBundle\Repository\AnalysisRepository") 
*/ 
class Analysis 

...

0

我认为你必须把唯一性逻辑放在你的实体上进行注释。

的src/HazardlogBu​​ndle /实体/ Analysis.php

/** 
    * @var string 
    * 
    * @ORM\Column(name="serial", type="integer", unique=true) 
    */ 
    private $serial; 
+0

它不是唯一的数据库,请参阅原始问题的更新 –

0

如果你正在使用MySQL - 你可以在不同的表使用AUTO_INCREMENT。你可以在mysql文档中找到更多:http://dev.mysql.com/doc/refman/5.6/en/information-functions.html#function_last-insert-id,参见“模拟序列”部分。

如果您正在使用PostgreSQL/ORACLE /等,您可以使用序列:https://www.postgresql.org/docs/9.5/static/functions-sequence.html

此外,您还可以使用uuid4和PHP生成它。这里获得重复密钥的机会非常低。

所有的案例(除mysql之外)都可以编码为单独的代码或作为原则的@GeneratedValuehttp://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html#identifier-generation-strategies
MySQL被排除,因为每个表只有一个AUTO_INCREMENT,并且可能已经将其用于主键。

+0

它不是唯一的数据库,请参阅原始问题的更新 –

+0

在我的文章中有独特的注意事项:)所有你需要的是原子计数器。 Postgresql序列是原子的,并不依赖于任何表。 MySQL的auto_increment是原子的,但是链接到表,并且每个表只有一个,所以你需要特殊的计数器表(参见mysql doc链接)。 Uuid很好,因为不需要请求数据库获取新的串口,你可以用你的php代码生成新的uuid4。 –