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

Hibernate 復合主鍵映射詳解:@EmbeddedId、@IdClass 與 XML 配置實戰

     編輯:Java 相關知識

什麼是復合主鍵

由**多個列共同唯一標識**一行記錄。常見於:多租戶表 (tenant_id + local_id)、關聯表 (student_id + course_id)、時間序列 (device_id + timestamp)。

核心要求

  1. 主鍵類必須實現 Serializable。
  2. 正確重寫 equals() 和 hashCode() (基於所有主鍵字段)。
  3. 提供無參構造器。

方案一:@EmbeddedId (推薦,對象化)

1. 主鍵類


@Embeddable
@Data @NoArgsConstructor @AllArgsConstructor
public class DepartmentPK implements Serializable {
    private String area;
    private String name;
}

2. 實體類


@Entity
@Table(name = "hibernate_dept_compositePK")
@Data @NoArgsConstructor
public class Department {
    @EmbeddedId
    private DepartmentPK departmentPK;

    private Integer empCount;
    private Date birthday;
}

3. 使用示例


Department dept = new Department();
dept.setDepartmentPK(new DepartmentPK("北京", "研發部"));
dept.setEmpCount(100);
dept.setBirthday(new Date());
session.save(dept);

// 查詢
DepartmentPK pk = new DepartmentPK("北京", "研發部");
Department loaded = session.get(Department.class, pk);

方案二:@IdClass (傳統,字段平鋪)


@Entity
@IdClass(DepartmentPK.class) // 指定主鍵類
@Table(name = "hibernate_dept_compositePK")
public class Department {
    @Id private String area;
    @Id private String name;
    private Integer empCount;
    private Date birthday;
    // Getter/Setter
}

// 主鍵類結構相同,但不需 @Embeddable
public class DepartmentPK implements Serializable {
    private String area;
    private String name;
    // equals/hashCode
}

查詢時同樣構造 PK 對象:session.get(Department.class, new DepartmentPK("北京", "研發部"))。

方案三:XML 映射 (遺留項目維護)

<hibernate-mapping>
  <class name="com.yangfei.hibernate.compositePk.entity.Department" table="hibernate_dept_compositePK">
    <composite-id name="departmentPK" class="com.yangfei.hibernate.compositePk.entity.DepartmentPK">
      <key-property name="area" />
      <key-property name="name" />
    </composite-id>
    <property name="empCount" />
    <property name="birthday" type="date" />
  </class>
</hibernate-mapping>

關鍵操作代碼對比

操作@EmbeddedId@IdClass
保存setDepartmentPK(pk) → save()直接 setArea/setName → save()
查詢 get/loadsession.get(Entity.class, pk)session.get(Entity.class, pk)
HQL 查詢from Department d where d.departmentPK.area = ?from Department d where d.area = ?
Criteria 查詢Restrictions.eq("departmentPK", pk)Restrictions.eq("area", "北京").add(Restrictions.eq("name", "研發部"))

最佳實踐建議

  1. **新項目優先 @EmbeddedId**:語義清晰、主鍵封裝性好、HQL/Criteria 更直觀。
  2. **主鍵類單獨放置**:便於多實體復用、DTO 傳輸、緩存 Key 復用。
  3. **equals/hashCode 必須穩定**:不要包含可變字段,推薦用 Lombok @EqualsAndHashCode 或 IDE 生成。
  4. **避免業務主鍵頻繁變更**:復合主鍵修改涉及關聯表級聯更新,成本極高;建議改用代理主鍵 (UUID/自增) + 唯一約束。

總結

Hibernate 提供 @EmbeddedId (對象化) 和 @IdClass (平鋪) 兩種註解方式映射復合主鍵,XML 配置同理。核心在於**主鍵類正确实现 Serializable/equals/hashCode**,以及理解兩種方式在查詢寫法上的差異。新項目推薦 @EmbeddedId,配合代理主鍵策略降低復雜度。

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