本ページはプロモーションが含まれています

Java入門

JavaのUUID完全ガイド!生成方法から注意点まで解説

UUID(生成方法と注意点)

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

Javaでの開発プロジェクトに携わっていると、「IDにはUUIDを使いましょう」という話をよく耳にします。

私自身、以前は大規模なマイクロサービスの開発で、どのバージョンのUUIDを選択すべきか頭を悩ませた経験があります。

特に、データベースのパフォーマンスに与える影響を考慮せず安易に導入してしまい、後から修正に苦労したこともありました。

この記事は、過去の私と同じように、

こんな方におすすめ

  • JavaでUUIDをどうやって生成すればいいか知りたい
  • UUIDの種類がたくさんあって、どれを使えばいいか分からない
  • UUIDを使うとパフォーマンスが落ちると聞いたけど、本当?

といった悩みを持つJava開発者の方に向けて書いています。

この記事を最後まで読めば、JavaにおけるUUIDの基本的な使い方から、実務で役立つ実践的な活用例、そして思わぬ落とし穴を避けるための注意点まで、体系的に理解できます。

自信を持ってUUIDを使いこなし、より安全で効率的な開発を進められるようになりましょう。

UUIDとは?Javaで使われる理由をわかりやすく解説

UUIDとは何かとJavaで使われる理由を示す図解

Java開発で頻繁に利用されるUUIDについて、その基本から見ていきましょう。なぜ多くのシステムでUUIDが採用されるのか、その理由を明らかにします。

UUIDの基本概念と仕組み

UUIDとは「Universally Unique Identifier」の略で、日本語では「汎用一意識別子」と訳されます。

その名の通り、世界中でほぼ一意(ユニーク)になるように設計された128ビットの識別子です。

123e4567-e89b-12d3-a456-426614174000

上記のような32桁の16進数と4つのハイフンで構成される文字列として表現されるのが一般的です。

UUIDは、タイムスタンプやコンピューターのMACアドレス、ランダムな数値などを組み合わせて生成されるため、異なる場所や時間で生成しても、重複する可能性が天文学的に低くなる仕組みになっています。

UUIDと通常のID(連番ID)の違い

システムで使われるIDには、データベースが自動で採番する「連番ID」(1, 2, 3...)もあります。

UUIDと連番IDには、それぞれメリットとデメリットが存在します。

項目UUID連番ID
一意性非常に高い(ほぼ重複しない)テーブル内でのみ一意
生成場所アプリケーション側で生成可能データベース側で生成
推測困難容易(次のIDが予測できる)
パフォーマンス書き込み時に劣る場合がある書き込み時に高速
データサイズ大きい(128ビット)小さい(64ビットなど)

UUIDはどこでも生成できて推測されにくいという強みを持つ一方で、データサイズやパフォーマンス面では連番IDに劣る部分があります。

なぜJavaでUUIDがよく使われるのか

では、なぜJava開発、特に近年のWebアプリケーション開発でUUIDが好んで使われるのでしょうか。主な理由は3つあります。

  1. 分散システムとの相性:複数のサーバーが協調して動作するマイクロサービスや分散システムでは、中央でIDを管理する仕組みがボトルネックになりがちです。UUIDなら各サーバーが独立してIDを生成できるため、IDの採番待ちが発生せず、システム全体のスケーラビリティが向上します。
  2. セキュリティの向上:連番IDは「/users/1」「/users/2」のように、次のIDが簡単に推測できてしまいます。これにより、他のユーザーの情報を不正に閲覧されるリスクが高まります。UUIDを使えばIDが推測されにくくなるため、セキュリティが向上します。
  3. オフラインでのデータ生成:クライアントサイド(例:スマートフォンアプリ)でデータを生成し、後からサーバーに送信するようなケースでも、UUIDは活躍します。クライアント側でユニークなIDを事前に発行できるため、通信が発生する前にデータを確定させられます。

これらの理由から、多くのJavaプロジェクトでUUIDが採用されているのです。

JavaでUUIDを生成する方法

JavaでUUIDを生成する方法を示す図解

JavaでUUIDを扱うのは簡単です。

標準ライブラリにjava.util.UUIDクラスが用意されているため、特別なライブラリを追加する必要はありません。

UUID.randomUUID()の使い方とサンプルコード

最も一般的に使われるのが、ランダムなUUID(バージョン4)を生成するrandomUUID()メソッドです。使い方はきわめてシンプルです。

java
import java.util.UUID;

public class UuidExample {
    public static void main(String[] args) {
        // UUIDを生成
        UUID uuid = UUID.randomUUID();

        // 生成したUUIDを文字列として出力
        System.out.println(uuid.toString());
        // 出力例: 550e8400-e29b-41d4-a716-446655440000
    }
}

このメソッドを呼び出すだけで、暗号学的に安全な乱数ジェネレーターを使って、ほぼ重複しないUUIDを簡単に取得できます。

固定値を使いたいときのUUID.fromString()の使い方

既存のUUID文字列からUUIDオブジェクトを生成したい場合は、fromString()メソッドを使います。

データベースから取得したID文字列を扱う際などによく利用されます。

java
import java.util.UUID;

public class UuidFromStringExample {
    public static void main(String[] args) {
        String uuidString = "123e4567-e89b-12d3-a456-426614174000";

        // 文字列からUUIDオブジェクトを生成
        UUID uuid = UUID.fromString(uuidString);

        System.out.println(uuid);
        // 出力: 123e4567-e89b-12d3-a456-426614174000
    }
}

ただし、指定する文字列がUUIDのフォーマットに準拠していない場合、IllegalArgumentExceptionという例外が発生するため注意が必要です。

UUIDの文字列変換(toString)と利用例

UUIDオブジェクトをデータベースに保存したり、APIのレスポンスとして返したりする際には、文字列への変換が必要です。

これにはtoString()メソッドを使います。

java
UUID uuid = UUID.randomUUID();
String uuidStr = uuid.toString(); // "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"形式

もしハイフンが不要な場合は、Stringクラスのreplace()メソッドを使って削除できます。

java
String uuidWithoutHyphen = uuid.toString().replace("-", "");
// "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"形式

URLのパスやリクエストパラメータとして使う場合など、用途に応じてハイフンの有無を選択すると良いでしょう。

UUIDの種類とバージョンの違い

UUIDの種類とバージョンの違いを示す図解

一言でUUIDといっても、実はいくつかの「バージョン」が存在します。

バージョンによって生成方法や特性が異なるため、用途に合ったものを選択することが重要です。

UUIDv1(時刻ベース)とUUIDv4(ランダム生成)の違い

特に有名なのがバージョン1(UUIDv1)とバージョン4(UUIDv4)です。

  • UUIDv1 (時刻ベース):生成した時刻(タイムスタンプ)と、コンピューターのネットワークカードに固有のMACアドレスを基に生成されます。
    • メリット: 時刻情報を含みますが、タイムスタンプが下位・中位・上位に分かれて並ぶため、そのままの並び順では時系列になりません。
    • デメリット: MACアドレスが含まれるため、どのコンピューターで生成されたか特定されるプライバシー上のリスクがあります。また、同じ時刻に同じコンピューターで複数生成すると重複の可能性があります(実際にはクロックシーケンスで回避されます)。
  • UUIDv4 (ランダム生成):時刻などの情報を使わず、完全にランダムな数値から生成されます。JavaのUUID.randomUUID()で生成されるのが、このバージョン4です。
    • メリット: 生成元に関する情報を含まないため、プライバシー面で安全です。最もシンプルで広く使われています。
    • デメリット: ランダムなため、生成順にソートできません。データベースのインデックス効率が悪くなる原因にもなります。

Javaで扱えるUUIDバージョンは?

JDK 25以前のJavaの標準ライブラリjava.util.UUIDでは、主にバージョン3とバージョン4の生成をサポートしていました。2026年3月にGAとなったJDK 26以降は、これに加えてバージョン7もネイティブでサポートしています。

  • バージョン4: UUID.randomUUID()で生成できます。
  • バージョン3: UUID.nameUUIDFromBytes()で生成できます。これは、名前(文字列など)を基にMD5で一貫したUUIDを生成する方法で、同じ名前からは必ず同じUUIDが生成されます。SHA-1を使うバージョン5を生成するメソッドは標準にありません。

標準ライブラリにはバージョン1を直接生成するメソッドは用意されていません。

もしv1を使いたい場合は、java-uuid-generator (JUG)などの外部ライブラリを利用する必要があります。

UUIDv7など新しい仕様との関係

近年、UUIDv7という新しいバージョンが注目されています。これはUUIDv1とUUIDv4の「良いとこ取り」をしたような仕様です。

UUIDv7は、先頭部分がタイムスタンプ(時刻情報)になっており、残りの部分がランダムな値で構成されています。これにより、以下のメリットが生まれます。

  • ソート可能: 時刻情報を持つため、IDで並べ替えができます。
  • パフォーマンス向上: データベースのインデックスにおいて、v4のようなランダムな値よりも効率的にデータを格納できるため、書き込みパフォーマンスの向上が期待できます。
  • プライバシー保護: v1と違い、MACアドレスを含まないため安全です。

2026年3月にGAとなったJDK 26からは、java.util.UUID.ofEpochMillis(long)メソッドでUUIDv7をネイティブに生成できるようになりました。

ミリ秒単位のUnixタイムスタンプを渡すだけで、RFC 9562準拠のUUIDv7が得られます。

java
import java.time.Instant;
import java.util.UUID;

public class Uuidv7Example {
    public static void main(String[] args) {
        // JDK 26以降: java.util.UUID.ofEpochMillis()でUUIDv7を生成
        UUID uuidV7 = UUID.ofEpochMillis(Instant.now().toEpochMilli());
        System.out.println(uuidV7);
    }
}

JDK 25以前の環境で動かす必要がある場合や、nameベース生成など高度な機能を使いたい場合は、引き続きuuid-creatorなどの外部ライブラリが選択肢になります。

データベースの主キーにUUIDの採用を検討している場合、UUIDv7は有力な選択肢となるでしょう。

UUIDを使う際の注意点と落とし穴

UUIDを使う際の注意点と落とし穴を示す図解

便利に見えるUUIDですが、何も考えずに使うと思わぬ問題に直面することがあります。ここでは、JavaUUIDを利用する上での3つの注意点を解説します。

重複の可能性は本当にゼロ?

結論から言うと、重複の可能性はゼロではありませんが、実用上はゼロと考えて問題ありません。

UUIDv4のバリエーション総数は約5.3×10^36という想像もつかないほどの数です。

1秒間に10億個のUUIDを生成し続けた場合、重複が発生する確率が50%に達するまでに約86年かかる計算です(誕生日問題による概算で、100年続けると約61%になります)。

一般的なWebアプリケーションの規模で重複を心配する必要はまずないでしょう。

あわせて読む

UUIDが長すぎるときの短縮方法

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxという36文字の形式は、URLに含めると長すぎると感じることがあるかもしれません。

その場合、いくつかの短縮方法が考えられます。

  • ハイフンを削除する: 32文字になります。
  • Base64エンコードする: UUIDは128ビット(16バイト)のデータなので、Base64エンコードすると、より短い文字列(約22文字)で表現できます。

ただし、短縮すると元のUUIDに戻す処理が必要になったり、人が目で見て識別しにくくなったりするデメリットもあるため、用途をよく考えて利用しましょう。

データベースでUUIDを使うときのパフォーマンス問題

これはUUIDを利用する上で最も注意すべき点です。

特に、データベースの主キー(Primary Key)にUUIDv4を使うと、深刻なパフォーマンス問題を引き起こす可能性があります。

  • インデックスの断片化:連番IDの場合、新しいデータはインデックスの末尾に追記されていくだけなので効率的です。しかし、完全にランダムなUUIDv4を主キーにすると、データの挿入場所がインデックスのあちこちに分散してしまいます。これによりインデックスの断片化が発生し、ページ分割が起きやすくなり、書き込み性能が低下する可能性があります。
  • データサイズ:UUIDは16バイトのデータです。一方、連番IDでよく使われるBIGINTは8バイトです。主キーのデータサイズが大きいと、インデックス全体のサイズも大きくなり、メモリをより多く消費し、検索性能にも影響を与えます。

対策としては、前述したUUIDv7のようなソート可能なUUIDを利用するのが最も効果的です。

ソート可能なUUIDであれば、データが時系列に沿ってインデックスに格納されるため、ランダムなUUIDv4よりインデックスへの挿入位置が分散しにくく、性能の低下を抑えやすくなります。

なお、MySQLの場合はUUID_TO_BIN()/BIN_TO_UUID()関数(MySQL 8.0以降)を使うと、Java側での文字列⇔バイナリ変換をSQL側に任せられ、アプリケーションコードをシンプルに保てます。

UUIDの活用例と実践コード

UUIDの活用例と実践コードを示す図解

理論だけでなく、実際にJavaでUUIDがどのように活用されているのか、具体的なコード例を交えて紹介します。

API開発でのUUID活用パターン

REST APIでリソースを識別するIDとしてUUIDを使うのは、一般的なパターンです。

java
// GET /users/123e4567-e89b-12d3-a456-426614174000 のようなリクエストを想定
@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{userId}")
    public ResponseEntity<User> getUserById(@PathVariable("userId") UUID userId) {
        User user = userService.findById(userId);
        return ResponseEntity.ok(user);
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User newUser) {
        // 新規作成時にUUIDを採番する
        newUser.setId(UUID.randomUUID());
        User createdUser = userService.save(newUser);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
    }
}

IDにUUIDを使うことで、URLから他のユーザーIDを推測されるのを防ぎ、セキュリティを高める効果があります。

ファイル名やセッションIDに使う例

ユーザーがアップロードしたファイルの名前が他のユーザーと重複しないように、ファイル名にUUIDを付与するのも良い方法です。

java
// 元のファイル名: profile.jpg
// UUID: a1b2c3d4-....
// 保存するファイル名: a1b2c3d4-....-profile.jpg

String originalFilename = "profile.jpg";
String uniqueFilename = UUID.randomUUID().toString() + "-" + originalFilename;

// このユニークなファイル名でサーバーに保存する

同様に、WebアプリケーションのセッションIDのように、一時的でユニークな識別子が必要な場合にもUUIDは最適です。

UUIDを使ったユニークキー設計のポイント

データベースの主キーにUUIDを使う場合は、パフォーマンスへの影響を常に意識する必要があります。

  • データ型:UUIDをVARCHAR(36)のような文字列型で保存するのは避けましょう。ストレージ効率が悪く、インデックス性能も低いです。多くのデータベースではUUID専用の型や、BINARY(16)のようなバイナリ型が用意されています。これらを利用するのがベストです。
  • バージョンの選択:前述の通り、書き込み性能が重要視されるテーブルでは、UUIDv4よりもUUIDv7のようなソート可能なUUIDの採用を強く推奨します。

これらのポイントを押さえることで、UUIDのメリットを享受しつつ、パフォーマンスの劣化を最小限に抑えられます。

まとめ:UUIDを理解すればJava開発がもっと楽になる

この記事では、JavaにおけるUUIDの基本から実践的な使い方、そして注意点までを網羅的に解説しました。最後に、重要なポイントを振り返りましょう。

UUIDのメリットを再確認

  • 世界で一つだけ: システムの規模や場所を問わず、ほぼ重複しないIDを生成できます。
  • どこでも生成可能: データベースに頼らず、アプリケーション側でIDを払い出せます。
  • 高いセキュリティ: IDがランダムなため、第三者による推測が困難です。

シーン別の使い分けまとめ

  • 外部に公開するID: セキュリティが重要なAPIのエンドポイントなどでは、UUIDv4が向いています。
  • DBの主キー: 書き込みパフォーマンスが求められる場合は、UUIDv7などのソート可能なUUIDを検討しましょう。
  • 小規模な内部システム: 必ずしもUUIDにこだわる必要はなく、従来の連番IDが適している場合もあります。

UUID関連のライブラリ・ツール紹介

Java標準ライブラリで不足を感じた場合は、以下のライブラリが役立ちます。

  • java-uuid-generator (JUG):UUIDv1を含む、さまざまなバージョンのUUIDを生成できる老舗ライブラリです。
  • uuid-creator:注目されているUUIDv7を簡単に生成できるライブラリで、新しいプロジェクトでの採用におすすめです。

UUIDは、現代のJavaアプリケーション開発において強力なツールです。

その特性と注意点を正しく理解し、適材適所で活用することで、あなたの開発プロジェクトはより堅牢でスケーラブルなものになるでしょう。

よくある質問

Q1. JavaでUUIDを生成するにはどうすればいいですか?

A1. 標準ライブラリのjava.util.UUIDクラスを使います。UUID.randomUUID()を呼び出すだけで、ランダムなUUID(バージョン4)を取得できます。

Q2. JavaでUUIDv7を生成できますか?

A2. JDK 26以降なら、UUID.ofEpochMillis()メソッドでネイティブに生成できます。JDK 25以前の環境ではuuid-creatorなどの外部ライブラリが必要です。

Q3. UUIDが重複する可能性はありますか?

A3. 理論上はゼロではありませんが、実用上は無視できるレベルです。UUIDv4のバリエーション総数は約5.3×10^36通りあり、一般的なWebアプリケーションの規模で重複を心配する必要はまずありません。

Q4. データベースの主キーにUUIDを使っても大丈夫ですか?

A4. UUIDv4をそのまま主キーにすると、インデックスの断片化で書き込み性能が低下する可能性があります。ソート可能なUUIDv7を使うと対策でき、データ型をBINARY(16)にするとサイズ面も軽減できます。

Q5. UUIDv1とUUIDv4はどう違いますか?

A5. UUIDv1は時刻とMACアドレスを基に生成され生成順を判別できますが、そのままの並び順では時系列になりません。また、生成元が特定されるリスクがあります。UUIDv4は完全にランダムでプライバシー面は安全ですが、生成順にソートはできません。

Q6. UUIDを短縮する方法はありますか?

A6. ハイフンを削除すれば36文字から32文字に、Base64エンコードすれば約22文字に短縮できます。ただし人が目で識別しにくくなる点に注意が必要です。

REVISIONS / 改訂履歴
REV.DATE内容
32026-10-04記載内容の事実確認と修正
22026-09-032026年9月時点の情報で全体を見直し(古い記述を3件更新)
12025-10-11初版
  • この記事を書いた人
  • 最新記事

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

-Java入門