複合主鍵 和 聯合主鍵的區別
複合主鍵 : 一張表中 , 兩個字段 確定一條唯一數據 ;
聯合主鍵 : 表A , 表 B 兩張表 , 通過中間表 , 確定兩張表的對應關係 ;
(中間表三個字段 : id , 表A_id, 表B_id) ; 此時中間表的id 稱爲 聯合主鍵 ;
spring jpa 複合主鍵 的使用
使用場景 : 訂單類的 , 訂單編號 ORDER_NUM + 訂單子項目 INNER_NUM , 兩個字段 組成 複合主鍵 , 確定唯一數據 ;
- 方式一 : 使用 @Embeddable 註解主鍵類 ; 然後 實體類 繼承自主鍵類 ; (該方式書寫簡潔, 但是不易懂)
1 . 編寫一個複合主鍵類 ; 命名可以在 實體類名後 + PK 用於 區分 主鍵類 ;
@Embeddable // 1. 在複合主鍵的類上,使用註解@Embeddable
public class OrderPK implements Serializable { // 2. 實現Serializable接口(否則會報錯);
@Column(name = "ORDER_NUM")
private String orderNum; // 主單號
@Column(name = "INNER_NUM")
private String innerNum; // 子項目
// 3. 無參構造
// 有默認的public無參數的構造方法(在我這個實例中,我沒有添加有參構造方法,所以採用默認的構造方法)
// 如果你在實體類裏有有參構造方法,那麼一定要有一個無參構造方法,否則運行的時候會報錯
// 4. 重寫equals和hashCode方法。
// equals方法用於判斷兩個對象是否相同,EntityManger通過find方法來查找Entity時,
// 是根據equals的返回值來判斷的。
// hashCode方法返回當前對象的哈希碼
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof OrderPK)) return false;
OrderPK orderPK = (OrderPK) o;
if (orderNum != null ? !orderNum.equals(orderPK.orderNum) : orderPK.orderNum != null) return false;
return innerNum != null ? innerNum.equals(orderPK.innerNum) : orderPK.innerNum == null;
}
@Override
public int hashCode() {
int result = orderNum != null ? orderNum.hashCode() : 0;
result = 31 * result + (innerNum != null ? innerNum.hashCode() : 0);
return result;
}
// 生成 get set toString 此處省略
}
2 . 編寫實體類 , 繼承 主鍵類;
@Entity
@Table(name = "ORDER")
public class Order extends OrderPK {
// 複合主鍵要用這個註解
@EmbeddedId
private OrderPK id;
// 複合主鍵的兩個字段, 在實體類中,就不用寫了
@Column(name = "OTHER_FIELD")
private String otherField; // 其他字段
// 生成 get set toString 此處省略
}
- 方式二 : 採用 @IdClass 來註解複合主鍵; ( 推薦 , 複合主鍵字段, 在實體類中, 直接有體現 , 看起來簡單明瞭)
1 . 編寫一個複合主鍵類;
// @Embeddable
public class OrderPK implements Serializable {
// @Column(name = "ORDER_NUM")
private String orderNum; // 主單號
// @Column(name = "INNER_NUM")
private String innerNum; // 子項目
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof OrderPK)) return false;
OrderPK orderPK = (OrderPK) o;
if (orderNum != null ? !orderNum.equals(orderPK.orderNum) : orderPK.orderNum != null) return false;
return innerNum != null ? innerNum.equals(orderPK.innerNum) : orderPK.innerNum == null;
}
@Override
public int hashCode() {
int result = orderNum != null ? orderNum.hashCode() : 0;
result = 31 * result + (innerNum != null ? innerNum.hashCode() : 0);
return result;
}
// 生成 get set toString 此處省略
}
2 . 編寫實體類
@Entity
@Table(name = "ORDER")
@IdClass(OrderPK.class) // 添加 @IdClass 註解 , 指定 複合主鍵類
public class Order implements Serializable { // 不用再繼承 複合主鍵類
// @EmbeddedId
// private OrderPK id;
@Id // 添加複合主鍵標識
@Column(name = "ORDER_NUM")
private String orderNum; // 主單號
@Id // 添加複合主鍵標識
@Column(name = "INNER_NUM")
private String innerNum; // 子項目
@Column(name = "OTHER_FIELD")
private String otherField; // 其他字段
// 生成 get set toString 此處省略
}