一意でランダムな6桁の数字

さのです。
メガネとカバンかってウキウキです。
ブログは少しサボってたので、少しがんばって更新します。
今回は新規登録したユーザーに一意なIDを振りたいと思います。

IDの条件
・6桁の数字(左0埋め)
・登録順がわからないようにランダムに振る
・一度振った番号は使わない
という感じです。DBはPostgreSQLを使います。
 

いろんなID採番方法

Javaにはランダムな文字列を作成するためのユーティリティーが沢山あります。 有名なのはこのあたりでしょうか。

クラス メソッド
UUID (Java Platform SE 8) randomUUIDメソッド
Math (Java Platform SE 8) randomメソッド
RandomStringUtils (Apache Commons Lang 3.5-SNAPSHOT API) randomNumericメソッド

この中ではRandomStringUtilsが数値のみで桁数指定できるので条件と合致しますが、そもそも6桁では100万通りしかないため、すぐに重複してしまいます。
すぐに思いつくのはDBを検索して同じ会員番号が無いことを確認し、重複があれば作り直すという処理にすることです。
しかし、それでは件数が増えるにつれ重複する確率が上がり、IDを生成する回数もDBにアクセスする回数も増えてしまいます。

どうせDBにアクセスするのであればDBで採番しましょう。
 

採番テーブルを利用する

まず、6桁のIDだけ持つテーブルを作成し、000000〜999999までのデータをINSERTします。

CREATE TABLE numbering(
id VARCHAR(6) NOT NULL
);

INSERT INTO numbering('000000');
・・・
INSERT INTO numbering('999999');

PostgreSqlにはRANDOMという関数が用意されており、うまく使うことでデータをランダムに取得することができます。

SELECT * FROM numbering ORDER BY RANDOM() LIMIT 1;

各データにランダムな数値を付加してその順番で並び替えを行い、先頭のデータを取得しています。
※LIMITの件数を変えることで好きな件数をランダムで取得することができます。

最後に取得したデータを削除して完了です。
この方法の利点は、未使用のIDの中から選択するので同じIDを取得してしまうことが無いところです。
また、避けたい番号(444444など)の制御もDBに登録しなければいいだけなので簡単にできます。
論理削除を活用すれば退会ユーザーのIDの再利用もできます。
 

注意

どちらの場合でも同様ですが、同時アクセスされると重複した番号を採番してしまう可能性があります。
最終的に登録するテーブルのIDにUNIQUE制約をかけて、同じIDが登録されたら例外エラーを発生させ採番し直すような処理にしたほうがいいでしょう。