孫衛琴的《精通JPA與Hibernate》的讀書筆記:映射一對多雙向關聯關係

當類與類之間創建了關聯,就能夠方便地從一個對象導航到另外一個或者一組與它關聯的對象。例如,對於給定的Order對象,若是想得到與它關聯的Customer對象,只要調用以下方法:java

//從Order對象導航到關聯的Customer對象
Customer customer=order.getCustomer();

在Order類中,用@ManyToOne註解映射customer屬性:數據庫

@ManyToOne(targetEntity =Customer.class)
  @JoinColumn(name="CUSTOMER_ID")
  private Customer customer;

對於給定的客戶,查詢該客戶的全部訂單,只須要調用customer.getOrders()方法。markdown

Hibernate要求在持久化類中定義集合類屬性時,必須把屬性聲明爲接口類型,如java.util.Set、java.util.Map和java.util.List。聲明爲接口能夠提升持久化類的透明性,當Hibernate調用setOrders(Set orders)方法時,傳遞的參數是Hibernate自定義的實現該接口的類的實例。若是把orders聲明爲java.util.HashSet類型(它是java.util.Set接口的一個實現類),就強迫Hibernate只能把HashSet類的實例傳給setOrders()方法。app

在定義Customer類的orders集合屬性時,一般把它初始化爲集合實現類的一個實例,例如:ide

private Set<order> orders=new HashSet<order>();

這能夠提升程序的健壯性,避免應用程序訪問取值爲null的orders集合的方法而拋出NullPointerException。例如,如下程序訪問Customer對象的orders集合,即便orders集合中不包含任何元素,可是調用orders.iterator()方法也不會拋出NullPointerException異常,由於orders集合並不爲null:this

Set<Order> orders=customer.getOrders();
Iterator<Order> it=orders.iterator();
while(it.hasNext()){
  ……
}

如下是Customer.java的源程序。atom

@Entity
@Table(name="CUSTOMERS")
public class Customer  implements java.io.Serializable {
  @Id
  @GeneratedValue(generator="increment")
  @GenericGenerator(name="increment", strategy = "increment")
  @Column(name="ID") 
  private Long id;

  @Column(name="NAME")
  private String name;

  @OneToMany(mappedBy="customer",
             targetEntity=Order.class,
             cascade=CascadeType.ALL)
  private Set<Order> orders = new HashSet<Order>();
  
  //此處省略構造方法,以及id和name屬性的訪問方法
  ……
  public Set<Order> getOrders(){
    return orders;
  }
  public void setOrders(Set<Order> orders) {
    this.orders=orders;
  }
}

對於Customer類的orders屬性,因爲在CUSTOMERS表中沒有直接與orders屬性對應的字段,所以不能用@Column註解來映射orders屬性,而是要使用@OneToMany註解。@OneToMany註解包括如下屬性。spa

  • targetEntity屬性:指定orders集合中存放的是Order對象。
  • mappedBy屬性:指定Order類中的customer屬性引用所關聯的Customer對象。
  • cascade:當取值爲CascadeType.ALL,表示會執行級聯保存、更新和刪除等操做。

在雙向關聯關係中,能夠把一方稱爲主動方,另外一方稱爲被動方。主動方會負責維護關聯關係,而被動方不負責維護關聯關係。被動方用@OneToOne、@OneToMany和@ManyToMany註解來映射,而且設置了mappedBy屬性。code

在Customer類與Order類的一對多雙向關聯關係中,Customer類爲「一」的一方,Order類爲「多」的一方。Customer類做爲「一」的一方,它的@OneToMany註解設置了mappedBy屬性,所以Customer類是被動方,而Order類是主動方,負責維護二者之間的關聯關係。
所謂維護關聯關係,有兩層含義:對象

  • (1)指在數據庫中,主動方Order類對應的ORDERS表的外鍵參照CUSTOMERS表。假如Customer類的@OneToMany註解沒有使用mappeBy屬性,那麼Customer類變成主動方,須要維護與Order類的關聯關係,此時須要建立額外的CUSTOMER_ORDER鏈接表。
  • (2)Hibernate會根據主動方的持久化對象的關聯關係的變化去同步更新數據庫。
    在這裏插入圖片描述
相關文章
相關標籤/搜索