首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Hibernate/JPA 實體映射聯合主鍵的三種標準姿勢(@Embeddable、@EmbeddedId、@IdClass)

     編輯:Java 綜合教學

背景

中間表、關聯表常無單列主鍵,需組合多列為聯合主鍵。Hibernate/JPA 提供三種映射方式,核心要求:**主鍵類必須實現 Serializable、重寫 equals/hashCode**。

方式一:@Embeddable + @Id(推薦,語義清晰)

主鍵類

@Embeddable
public class OrderItemKey implements Serializable {
    private Long orderId;
    private Long productId;

    // 無參構造、getter/setter、equals/hashCode 必須完整實現
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof OrderItemKey)) return false;
        OrderItemKey that = (OrderItemKey) o;
        return Objects.equals(orderId, that.orderId) && Objects.equals(productId, that.productId);
    }
    @Override
    public int hashCode() { return Objects.hash(orderId, productId); }
}

實體類

@Entity
@Table(name = "order_item")
public class OrderItem {
    @Id
    private OrderItemKey id; // 組合主鍵作為單一字段

    private int quantity;
    private BigDecimal price;
    // getter/setter
}

優點:主鍵封裝性好,實體類乾淨;缺點:查詢時需構造 Key 對象(em.find(OrderItem.class, new OrderItemKey(1L, 2L)))。

方式二:@EmbeddedId(主鍵類無需 @Embeddable)

主鍵類(普通類即可,但建議加 @Embeddable)

public class OrderItemKey implements Serializable {
    private Long orderId;
    private Long productId;
    // equals/hashCode/getter/setter
}

實體類

@Entity
public class OrderItem {
    @EmbeddedId
    private OrderItemKey id; // 直接嵌入

    private int quantity;
}

與方式一幾乎等價,@EmbeddedId 語義更明確:「這是一個嵌入式主鍵」。

方式三:@IdClass(主鍵字段平鋪在實體類中)

主鍵類

public class OrderItemKey implements Serializable {
    private Long orderId;
    private Long productId;
    // equals/hashCode/getter/setter
}

實體類

@Entity
@IdClass(OrderItemKey.class) // 指定主鍵類
public class OrderItem {
    @Id
    private Long orderId; // 主鍵字段直接在實體中

    @Id
    private Long productId;

    private int quantity;
}

優點:字段平鋪,JPQL 查詢直接用 WHERE o.orderId = :oid,無需攜帶 Key 對象;缺點:實體類字段冗余,主鍵類與實體類字段需**名稱、類型完全一致**。

三種方式對比選型指南

維度@Embeddable + @Id@EmbeddedId@IdClass
主鍵類注解@Embeddable無需(建議加)無需
實體類字段單一 Key 字段單一 Key 字段多個 @Id 字段平鋪
查詢/查找方式em.find(Entity, Key)em.find(Entity, Key)em.find(Entity, Key) 或單獨字段
JPQL 友好度需 join/key 訪問同左直接訪問字段,最友好
遷移舊代碼適合新設計適合新設計適合從 Hibernate XML 遷移
推薦場景領域驅動設計、值對象建模同上,語義更強傳統 DAO、大量 JPQL 查詢

關鍵避坑指南

  1. 主鍵類必須實現 Serializable,否則分布式環境/二級緩存會報錯。
  2. equals/hashCode 必須基於所有主鍵字段,且與 @Id 字段一致。
  3. 主鍵類字段名與實體類 @Id 字段名完全一致(@IdClass 模式下強制)。
  4. 不要在主鍵類中包含非主鍵字段,保持純粹。
  5. 組合主鍵類建議定義為 public static class 內部類或獨立類,便於管理。

總結

三種方式各有優勢,**新項目推薦 @EmbeddedId**(語義最清晰、封裝性最好);**大量 JPQL 查詢的傳統項目用 @IdClass**;避免混用。牢記:主鍵類 = Serializable + equals/hashCode + 字段一致性,這是聯合主鍵映射的鐵律。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved