孙卫琴的《精通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会根据主动方的持久化对象的关联关系的变化去同步更新数据库。
    在这里插入图片描述
相关文章
相关标签/搜索