5.

【Springエラー】No identifier specified for entity : ...

編集
この記事の要点
  • No identifier specified for entityJPA エンティティに @Id が付いていない
  • 対処: クラス内のどれか 1 つのフィールドに @Id を付ける
  • 複合キーの場合は @IdClass または @EmbeddedId
  • 主キー自動生成は @GeneratedValue(strategy = GenerationType.IDENTITY) など

 

エラーの状況

org.hibernate.AnnotationException:
No identifier specified for entity: com.example.User

JPA / Hibernate のエンティティは主キーが必須で、@Id アノテーションでフィールドを 1 つ指定する必要があります。

基本的な解決

// ダメな例
@Entity
@Table(name = "users")
public class User {
    private Long id;  // ← @Id がない!
    private String name;
}

// 修正
@Entity
@Table(name = "users")
public class User {
    @Id  // ← 必須
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}

主キー生成戦略

戦略説明対応 DB
IDENTITYDB の AUTO_INCREMENT / IDENTITY 列MySQL / PostgreSQL / SQL Server
SEQUENCEDB シーケンスから取得Oracle / PostgreSQL / DB2
AUTODB に応じて自動選択標準
TABLE専用テーブルでカウンタ管理すべての DB(パフォーマンス低)
UUIDUUID 自動生成 (Hibernate 6+)標準
指定なしアプリ側で値を設定

例: 各戦略

// IDENTITY (MySQL / PostgreSQL の AUTO_INCREMENT)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

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

// UUID
@Id
@GeneratedValue(strategy = GenerationType.UUID)  // Hibernate 6+
private UUID id;

// アプリ側で生成
@Id
private String code;  // 例: "USR-2026-001" を自分でセット

複合主キー (Composite Key)

複数フィールドで主キーを構成する場合。

方法 1: @IdClass

// 別途主キークラスを定義 (equals/hashCode 必須)
public class OrderItemId implements Serializable {
    private Long orderId;
    private Long productId;

    public OrderItemId() {}
    public OrderItemId(Long orderId, Long productId) {
        this.orderId = orderId;
        this.productId = productId;
    }

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

// エンティティで @IdClass を指定
@Entity
@IdClass(OrderItemId.class)
public class OrderItem {
    @Id
    private Long orderId;

    @Id
    private Long productId;

    private int quantity;
}

方法 2: @EmbeddedId(推奨)

// 埋め込み可能クラスとして定義
@Embeddable
public class OrderItemId implements Serializable {
    @Column(name = "order_id")
    private Long orderId;

    @Column(name = "product_id")
    private Long productId;

    public OrderItemId() {}
    public OrderItemId(Long orderId, Long productId) {
        this.orderId = orderId;
        this.productId = productId;
    }

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

@Entity
public class OrderItem {
    @EmbeddedId
    private OrderItemId id;

    private int quantity;
}

// 検索
OrderItem item = repository.findById(new OrderItemId(orderId, productId)).orElseThrow();

UUID 主キーの推奨パターン

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)  // Hibernate 6+
    @Column(columnDefinition = "VARCHAR(36)")  // または BINARY(16)
    private UUID id;
}

// Hibernate 5 以前
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
@Column(columnDefinition = "char(36)")
private String id;

主キーの設計指針

  • 自然キー vs 代理キー: 自然キー(メールアドレス等)より代理キー(id)が推奨。変更耐性・パフォーマンス・JOIN 効率の面で有利
  • Long vs UUID: 単一 DB なら Long (連番)、分散システムなら UUID
  • 複合キー: 中間テーブル以外では避ける(コードが複雑になる)
  • IDENTITY の制約: バッチ INSERT で 1 件ずつ ID 取得が必要、SEQUENCE のほうが効率的

関連エラー

  • Multiple identifiers specified for entity: @Id を複数フィールドに付けた(複合キーの場合は @IdClass/@EmbeddedId
  • Cannot determine identifier from a null id: ID が null のまま永続化を試みた
  • id to load is required for loading: find に null を渡した
  • detached entity passed to persist: 既に管理されたエンティティを persist しようとした

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. java.lang.IllegalStateException: CGLIB is required to process @Configuration classes
  2. Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
  3. No mapping found for HTTP request with URI ... in DispatcherServlet with name ...
  4. An internal error occurred during: "Building UI model". com/google/common/base/Function
  5. No identifier specified for entity : ...
  6. org.hibernate.hql.internal.ast.QuerySyntaxException: table_name is not mapped
  7. No compiler is provided in this environment
  8. java.sql.SQLException: The server time zone value ' ... ' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone
  9. Caused by: java.lang.RuntimeException: Executing an update/delete query
  10. Not supported for DML operations
  11. Field ... required a bean of type ... hat could not be found.
  12. Annotation-specified bean name ' ... ' for bean class [ ... ] conflicts with existing, non-compatible bean definition of same name and class [...]
  13. Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback.
  14. Exception in thread "main" java.lang.UnsupportedClassVersionError