t_customers:客戶表(主表)t_orders:訂單表(從表),含外鍵 customer_id 參考客戶表
@Entity
@Table(name = "t_customers")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
private Collection<Order> orders;
// Getter/Setter 略...
}
@Entity
@Table(name = "t_orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String productId;
private int count;
@ManyToOne
@JoinColumn(name = "customer_id")
private Customer customer;
// Getter/Setter 略...
}
重點:
@JoinColumn 指定外鍵欄位。mappedBy = "customer" 宣告由對方維護。cascade = CascadeType.ALL 確保客戶操作自動級聯至訂單。若不想在 t_orders 加外鍵,可引入關聯表 t_customers_orders:
@OneToMany
@JoinTable(
name = "t_customers_orders",
joinColumns = @JoinColumn(name = "t_customers_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "orders_id", referencedColumnName = "id")
)
public Collection<Order> getOrders() { return orders; }
此時 Order 實體不再需要 customer 欄位與對應的 Getter/Setter。
Customer customer = new Customer();
customer.setName("微軟");
List<Order> orders = new ArrayList<>();
Order o1 = new Order(); o1.setProductId("1234"); o1.setCount(20); o1.setCustomer(customer);
Order o2 = new Order(); o2.setProductId("4321"); o2.setCount(12); o2.setCustomer(customer);
orders.add(o1); orders.add(o2);
customer.setOrders(orders);
em.persist(customer); // 級聯儲存訂單
| 特性 | 外鍵方式 | 關聯表方式 |
|---|---|---|
| 資料庫結構 | 從表含外鍵 | 額外關聯表,從表無外鍵 |
| 實體設計 | 雙向關聯,Order 有 customer 參考 | 單向關聯,Order 無 customer 參考 |
| 適用場景 | 標準一對多,需從 Order 導航至 Customer | 不想污染從表結構、或多對多語義 |