12.

【Spring】@Idアノテーションとは

編集
この記事の要点
  • @Id は JPA エンティティの主キーを指定するアノテーション
  • 各エンティティに必ず 1 つ(または複合キーで複数)必要
  • @GeneratedValue で自動採番を指定: IDENTITY / SEQUENCE / AUTO / UUID
  • 複合キー: @IdClass または @EmbeddedId
  • 型: Long / Integer / UUID / String

 

@Id の基本

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;
}

@Id必須です。なければ起動時に No identifier specified for entity エラー。

主キー生成戦略 (@GeneratedValue)

戦略動作主な DB
IDENTITYDB の AUTO_INCREMENT に任せるMySQL / PostgreSQL / SQL Server
SEQUENCEDB シーケンスから取得Oracle / PostgreSQL / DB2
TABLEカウンタテーブルから取得すべての DB(パフォーマンス低)
AUTOJPA プロバイダが選択DB 依存
UUIDUUID 自動生成(Hibernate 6+)標準

IDENTITY(MySQL / PostgreSQL 標準)

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

# 生成される DDL
# MySQL
CREATE TABLE users (
    id BIGINT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
);

# PostgreSQL
CREATE TABLE users (
    id BIGSERIAL NOT NULL PRIMARY KEY,
    ...
);

SEQUENCE(Oracle / PostgreSQL 推奨)

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
@SequenceGenerator(name = "user_seq", sequenceName = "user_sequence", allocationSize = 50)
private Long id;

# allocationSize: 一度に取得する ID の個数 (50 だと 50 個まとめて取って、JVM 内で順次使う)
# → DB アクセスが減り、バッチ INSERT が速くなる

# 生成される DDL
CREATE SEQUENCE user_sequence INCREMENT BY 50;

UUID(Hibernate 6+ / 分散システム向け)

@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(columnDefinition = "VARCHAR(36)")  // または BINARY(16)
private UUID id;

# 自動で UUID が割り当てられる
# 利点: DB に依存せず生成可能、分散システムで衝突しない
# 欠点: 長い (36 文字)、ソート効率が悪い

アプリ側で生成(@GeneratedValue なし)

@Id
private String code;  // 例: "USR-2026-001" を自分でセット

User user = new User();
user.setCode("USR-2026-001");
userRepository.save(user);

複合キー(Composite Primary Key)

方法 1: @IdClass

// 別のクラスで主キーを表現
public class OrderItemId implements Serializable {
    private Long orderId;
    private Long productId;

    public OrderItemId() {}
    public OrderItemId(Long o, Long p) { orderId = o; productId = p; }

    @Override public boolean equals(Object o) { ... }
    @Override public int hashCode() { ... }
}

@Entity
@IdClass(OrderItemId.class)
public class OrderItem {
    @Id private Long orderId;
    @Id private Long productId;
    private int quantity;
}

// 検索
OrderItem item = em.find(OrderItem.class, new OrderItemId(1L, 2L));

方法 2: @EmbeddedId(推奨)

@Embeddable
public class OrderItemId implements Serializable {
    @Column(name = "order_id") private Long orderId;
    @Column(name = "product_id") private Long productId;
    // equals/hashCode + コンストラクタ
}

@Entity
public class OrderItem {
    @EmbeddedId
    private OrderItemId id;
    private int quantity;
}

// 検索
OrderItem item = em.find(OrderItem.class, new OrderItemId(1L, 2L));

関連エンティティの主キー(@MapsId)

// User と UserProfile が 1 対 1、主キーを共有
@Entity
public class UserProfile {
    @Id
    private Long id;  // user_id と同じ値

    @MapsId  // id を user.id にマップ
    @OneToOne
    @JoinColumn(name = "id")
    private User user;
}

主キーの型選択

用途備考
Long標準的な自動採番連番、ソート効率良い、最大 9 京
Integer小規模システム20 億まで、将来オーバーする可能性
UUID分散システム衝突なし、長い、ソート効率低
String自然キー(コード等)変更困難、ビジネス的に変わると面倒
BigInteger暗号系・巨大数

主キーに関する設計指針

  • 自然キーより代理キー (id): 変更耐性が高い、JOIN が効率的
  • 主キーは不変: 一度設定したら変更しない
  • 主キーは公開しない: API では別の識別子(slug, code)を使う設計も検討
  • 連番 ID の連番性に依存しない: 抜けがあっても気にしない
  • UUID の保存形式: VARCHAR(36) は人間に読みやすい、BINARY(16) は容量・速度効率良い

よくある問題

Q. INSERT が遅い (IDENTITY 戦略)

IDENTITY だとバッチ INSERT が効かない(1 件ずつ ID を取りに行く)。大量 INSERT なら SEQUENCE + allocationSize を大きくする:

@SequenceGenerator(name = "user_seq", sequenceName = "user_seq", allocationSize = 100)

Q. ID が連番にならない

SEQUENCE で allocationSize が大きいと、再起動時に予約 ID 内で抜けが発生します。これは正常動作で、ID 連続性は気にしないべき。

Q. 楽観ロック

@Entity
public class User {
    @Id private Long id;
    @Version
    private Long version;  // ← 楽観ロック用バージョン番号
    // ...
}
// 同時更新が起きると OptimisticLockingFailureException

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. @After
  2. @Autowired
  3. @Bean
  4. @Before
  5. @Column
  6. @Component
  7. @Configuration
  8. @Controller
  9. @Data
  10. @Entity
  11. @GeneratedValue
  12. @Id
  13. @Modifying
  14. @PathVariable
  15. @PropertySource
  16. @Repository
  17. @RequestBody
  18. @RequestMapping
  19. @ResponseBody
  20. @RestController
  21. @Service
  22. @SpringBootApplication
  23. @Table
  24. @Transactional
  25. @Value