单向一对多的关联关系
具体体现:1的一方有n的一方的集合的引用,n的一方却没有1的一方的引用
举个例子:顾客Customer对订单Order是一个单向一对多的关联关系。Customer一方有对Order的集合的引用。而Order却没有对Customer的引用;
“一对多”的物理意义就是:一个客户可以有多个订单,而一个订单只能归属于一个客户。
“单向”的物理意义就是:客户知道自己有哪些订单,但是订单却不知道自己属于哪个客户(这个容易让人接受一点儿!!!但是,不满足某些业务需求)
同样的,下面看看“单向一对多”的“Customer对Order”会有什么变化:
Order实体的属性(Order中没有对Customer的引用):
1 @Table(name="t_single_one2many_order") 2 @Entity 3 public class Order1 { 4 5 private Integer id; 6 private String orderName; 7 8 //省略getter、setter方法... 9 }
Customer实体的属性(Customer中有对Order的集合的引用):
1 @Table(name="t_single_one2many_customer") 2 @Entity 3 public class Customer1 { 4 5 private Integer id; 6 private String lastName; 7 8 private String email; 9 private int age; 10 11 private Date birthday; 12 13 private Date createdTime; 14 15 //Customer1中有对Order1的集合引用 16 private Set<Order1> orders = new HashSet<Order1>(); 17 18 //省略getter、setter方法... 19 }
映射单向一对多的关联关系有两个要点:
1、利用@OneToMany注解进行一对多的映射;
2、利用@JoinColumn来映射外键列的名称;
注意的点:
1、@OneToMany的默认检索策略为延迟加载策略,可以通过设置其属性fetch=FetchType.EAGER来修改为立即检索策略;
2、@OneToMany设置的单向一对多关联在其默认情况下可以删除1的一方。
处理方式:首先将其关联的n的一方数据表的所有外键都设置为null,然后再删除1的一方。可以通过设置@OneToMany的属性cascade={CascadeType.REMOVE}来设置为级联删除(删除1的一方的同时把多的一方也同时删除,还可以设置其它的删除策略)
在实体类中,属性可以分为两种:1、集合属性; 2、非集合属性;
一个大体的原则就是:1、对集合属性默认采用懒加载策略;2、对非集合属性默认采用立即检索策略;
这种默认检索策略是有道理的:1、检索的时候我们并不知道集合中到底包含了多少条记录,可能是几条,也可能是几十亿条记录。如果对一个庞大的集合属性采用立即检索策略,那么很有可能直接将内存全部占用了(比如说,集合中包含了100亿条记录),系统直接崩溃。2、对一个非集合属性而言,即便是一个其它实体类的引用(该引用中的集合依然会采用延迟检索)所占资源也是十分有限,不会像检索集合那样直接脱离我们的掌控。所以,对于非集合属性默认采用立即检索策略。
对于单向1-n而言,保存的顺序没有差别,都会有update语句发送。
List_1. Order1实体的代码(不包含对1的一方的引用,不需要做任何关于映射的注解)
1 package com.magicode.jpa.single.one2many; 2 3 import javax.persistence.Column; 4 import javax.persistence.Entity; 5 import javax.persistence.GeneratedValue; 6 import javax.persistence.GenerationType; 7 import javax.persistence.Id; 8 import javax.persistence.Table; 9 import javax.persistence.TableGenerator; 10 11 @Table(name="t_single_one2many_order") 12 @Entity 13 public class Order1 { 14 15 private Integer id; 16 private String orderName; 17 18 @TableGenerator(name="order_id_generator_1", 19 table="t_id_generator", 20 pkColumnName="PK_NAME", 21 pkColumnValue="seedId_t_order_1", 22 valueColumnName="PK_VALUE", 23 initialValue=0, 24 allocationSize=20) 25 @GeneratedValue(generator="order_id_generator_1", strategy=GenerationType.TABLE) 26 @Id 27 @Column(name="ID") 28 public Integer getId() { 29 return id; 30 } 31 32 @Column(name="ORDER_NAME") 33 public String getOrderName() { 34 return orderName; 35 } 36 37 @SuppressWarnings("unused") 38 private void setId(Integer id) { 39 this.id = id; 40 } 41 42 public void setOrderName(String orderName) { 43 this.orderName = orderName; 44 } 45 46 }