由**多個列共同唯一標識**一行記錄。常見於:多租戶表 (tenant_id + local_id)、關聯表 (student_id + course_id)、時間序列 (device_id + timestamp)。
Serializable。equals() 和 hashCode() (基於所有主鍵字段)。
@Embeddable
@Data @NoArgsConstructor @AllArgsConstructor
public class DepartmentPK implements Serializable {
private String area;
private String name;
}
@Entity
@Table(name = "hibernate_dept_compositePK")
@Data @NoArgsConstructor
public class Department {
@EmbeddedId
private DepartmentPK departmentPK;
private Integer empCount;
private Date birthday;
}
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);
@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("北京", "研發部"))。
<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/load | session.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", "研發部")) |
@EqualsAndHashCode 或 IDE 生成。Hibernate 提供 @EmbeddedId (對象化) 和 @IdClass (平鋪) 兩種註解方式映射復合主鍵,XML 配置同理。核心在於**主鍵類正确实现 Serializable/equals/hashCode**,以及理解兩種方式在查詢寫法上的差異。新項目推薦 @EmbeddedId,配合代理主鍵策略降低復雜度。