實現Entity Bean的一對多(one-to-many)映射
EJB3的一對多映射使用@OneToMany來設置,如果是雙向的一對多映射,在many方需要使用@ManyToOne 設置。在本書中給出兩個表,其他一個表t_customers在上一篇文章中已給出了,另一個表的結構如圖1所 示。
圖1 t_orders表
t_customers和t_orders表是一對多關系,一個Customer可能有多個Order,而一個Order只能有一個 Customer。
在Customer類中需要定義一個集合類型的屬性,用來保存多個Order對象,Customer類的代碼如下:
package entity; import java.util.Collection; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; @Entity @Table(name = "t_customers") public class Customer { private int id; private String name; private Referee referee; private Collection<Order> orders; @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL) public Collection<Order> getOrders() { return orders; } public void setOrders(Collection<Order> orders) { this.orders = orders; } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public int getId() { return id; } ... ... }
其中@OneToMany的mappedBy屬性指定了Order類中獲得Customer對象的屬性名。Order類的代碼如下:
package entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinColumns; import javax.persistence.JoinTable; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name = "t_orders") public class Order { private int id; private String productId; private int count; private Customer customer; @ManyToOne @JoinColumn(name = "customer_id") public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public int getId() { return id; } ... ... }
其中@JoinColumn注釋的name屬性指定t_orders表中用於連接t_customers表的外鍵名。
可以使用下面的代碼進行測試:
Customer customer = new Customer(); customer.setName("微軟"); List<Order> orders = new ArrayList<Order>(); Order order =new Order(); order.setProductId("1234"); order.setCount(20); order.setCustomer(customer); orders.add(order); order = new Order(); order.setProductId("4321"); order.setCount(12); order.setCustomer(customer); orders.add(order); customer.setOrders(orders); em.persist(customer);
除此之外,還可以使用@JoinTable指定連接表來映射one-to-many關系。連接表的結構如圖2所示。
圖2 t_customers_orders表
首選需要將Customer類的getOrders方法修改成下的形式:
@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; }
其中name屬性指定圖2所示的連接表的名稱。joinColumns指定了t_customers表和t_customers_orders 表中相連接的字段。inverseJoinColumns指定了t_orders表和t_customers_orders表中相連接的字段。這 時t_orders表中的customer_id字段就不再需要了。因此,需要將Order表中的customer屬性(getter和 setter方法)去掉。
在持久化Customer和Order對象時,需要對Order對象進行持久化後才能對Customer對象進行持久化。