2016-11-11 2 views
0

Ich habe ein Dokumenten-Management-System in symfony2. Sobald der Benutzer seine Dokumenteneinheit eingerichtet hat, wird ihm eine Seriennummer zugewiesen.symfony2 wie garantie Seriennummer nicht verwendet

So finde ich die zu belegende Seriennummer 1) Check DB für die höchste verwendete serielle Schnittstelle 2) Ordnen Sie sie zu und spülen Sie die Einheit.

Ich verwende diese Seriennummer als eine Kennung für mehrere Versionen dieser Entität, so dass es nicht eindeutig für die DB ist.

Wie kann ich garantieren, dass die zugewiesene Nummer wirklich einzigartig ist? Ich würde Tabellen in Flat-PHP sperren, aber nicht sicher, wie es geht oder ob es in Symfony2 am besten funktioniert.

/** 
* 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

Ich muss offensichtlich clearify: ich haben kann ...

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 

Was ich bin Angst davor ist, dass Benutzer gleichzeitig Entität C und D erstellen, und so mein Controller die aktuell höchste Seriennummer abrufen konnte, die zum Erstellen von Entität C verwendet wird, und bevor Entität C in DB gelöscht wird, liest der Thread, der den Benutzer D liefert, am höchsten Nummer 123 aus der DB vor Entity C mit Seriennummer 124 wird in DB geschrieben. So werde ich mit Entity C & D beide mit der seriellen 124 enden.

Vielleicht könnte ich einen eindeutigen Index bestehend aus Serien-und Versionsnummer zusammen definieren, um dieses Problem zu umgehen?

+0

hat einen Blick auf Lehre Sperrtabelle Unterstützung: http: // docs. document-project.org/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency.html # locking-support – erwan

Antwort

0

fand ich einen Weg, um einen eindeutigen Index wie dies durch die Kombination von zwei Spalten zu erstellen:

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

...

0

Ich denke, Sie müssen die Eindeutigkeitslogik auf Ihre Entität mit Annotation setzen.

src/HazardlogBundle/Entity/Analysis.php

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

Es ist nicht einzigartig für die DB, siehe Update auf die ursprüngliche Frage –

0

Wenn Sie MySQL verwenden - Sie AUTO_INCREMENT auf separaten Tabelle verwenden können. Sie finden mehr in mysql-Dokumentation: http://dev.mysql.com/doc/refman/5.6/en/information-functions.html#function_last-insert-id, siehe Abschnitt "Sequenzen simulieren".

Wenn Sie PostgreSQL/Oracle/etc verwenden, können Sie Sequenzen verwenden: https://www.postgresql.org/docs/9.5/static/functions-sequence.html

Auch können Sie verwenden uuid4 und es in PHP generieren. Hier ist die Wahrscheinlichkeit sehr gering, einen doppelten Schlüssel zu erhalten.

Alle Fälle (außer mysql eins) können als separater Code oder als Doktrin @GeneratedValue kodiert werden. http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html#identifier-generation-strategies
MySQL ausgeschlossen, weil nur eine AUTO_INCREMENT pro Tabelle, und Sie wahrscheinlich bereits für den Primärschlüssel verwendet werden.

+0

Es ist nicht einzigartig für die DB, siehe Update auf die ursprüngliche Frage –

+0

Es gibt Hinweise auf einzigartige in meinem Beitrag :) Alles, was Sie brauchen, ist Atomzähler . Die Postgresql-Sequenz ist atomar und hängt von keiner Tabelle ab. Das auto_increment von MySQL ist atomar, aber mit der Tabelle und nur einem pro Tabelle verknüpft. Daher benötigen Sie eine spezielle Tabelle für den Zähler (siehe mysql doc link). Uuid gut, weil keine Datenbank zum Abrufen neuer Serien anfordern müssen, können Sie neue UUID4 mit Ihrem PHP-Code generieren. –