~/home of geeks

Zufälle sind nicht eindeutig

· 206 Wörter · 1 Minute(n) Lesedauer

thousands of dices rolling on a diceball table, photography, shallow depth

Neulich stolperte ich in einem Projekt über Duplicate-Entry-Exceptions auf der Datenbank, die in einem Testcase verursacht wurden.

Offensichtlich ging es dabei um doppelte Einträge in einer Unique-Datenbankspalte. Die Exception hatte folgende Form: ConstraintViolationException: Duplicate entry '1470773328' for key 'UNIQUE_NAME'. Die verursachende Stelle war ein Testcase, der zwei Datensätze erzeugte und speicherte:

Kategorie testKategorie1 = new Kategorie();
testKategorie1.setUniqueName(System.currentTimeMillis());
kategroieDao.save(testKategorie1);

Kategorie testKategorie2 = new Kategorie();
testKategorie2.setUniqueName(System.currentTimeMillis());
kategroieDao.save(testKategorie2);

// ...

Auf allen Rechnern lief der Test durch, nur nicht auf meinem. Im Testcase wurde statt einer eindeutigen ID eine “Zufallszahl”, hier behelfsmäßig die aktuelle Systemzeit) genommen, damit jede Entity einen eigenen, eindeutigen Namen erhielt. Interessanterweise lief der Code-Abschnitt anscheinend auf meinem Rechner so schnell durch, dass System.currentTimeMillis() zwei mal den selben Zeitstempel lieferte, was zu meinem Problem führte. Ich änderte es auf ein UUID.randomUUID() und voila: Der Testcase lief wieder erfolgreich. Eine Suche auf dem Code nach System.currentTimeMillis() offenbarte einige weitere Stellen, an denen die Systemzeit als zufällige ID benutzt wurde.

Gleichermaßen fand ich Code, der new Random.nextInt() als zufälligen ID-Generator missbrauchte. Auch wenn die Wahrscheinlichkeit, zwei mal die gleiche Nummer aus dem Zufallsgenerator zu erhalten, recht gering ist, sie tritt häufiger auf als man denkt. In diesem Sinne sollte man für eindeutige IDs die dafür vorgesehene UUID-Klasse benutzen.