7、单向一对多的关联关系(1的一方有n的一方的集合属性,n的一方却没有1的一方的引用)

单向一对多的关联关系

具体体现: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 }
Order1.java作为n的一方不需要任何关于映射的注解

List_2. Customer1实体的代码(包含有对n的一方的集合的引用

  1 package com.magicode.jpa.single.one2many;
  2 
  3 import java.util.Date;
  4 import java.util.HashSet;
  5 import java.util.Set;
  6 
  7 import javax.persistence.CascadeType;
  8 import javax.persistence.Column;
  9 import javax.persistence.Entity;
 10 import javax.persistence.FetchType;
 11 import javax.persistence.GeneratedValue;
 12 import javax.persistence.GenerationType;
 13 import javax.persistence.Id;
 14 import javax.persistence.JoinColumn;
 15 import javax.persistence.OneToMany;
 16 import javax.persistence.Table;
 17 import javax.persistence.TableGenerator;
 18 //import javax.persistence.TableGenerator;
 19 import javax.persistence.Temporal;
 20 import javax.persistence.TemporalType;
 21 import javax.persistence.Transient;
 22 
 23 /**
 24  * @Entity 用于注明该类是一个实体类
 25  * @Table(name="t_customer") 表明该实体类映射到数据库的 t_customer 表
 26  */
 27 @Table(name="t_single_one2many_customer")
 28 @Entity
 29 public class Customer1 {
 30 
 31     private Integer id;
 32     private String lastName;
 33 
 34     private String email;
 35     private int age;
 36     
 37     private Date birthday;
 38     
 39     private Date createdTime;
 40     
 41     private Set<Order1> orders = new HashSet<Order1>();
 42 
 43     @TableGenerator(name="ID_GENERATOR_1",
 44             table="t_id_generator",
 45             pkColumnName="PK_NAME",
 46             pkColumnValue="seedId_t_customer_1",
 47             valueColumnName="PK_VALUE",
 48             allocationSize=20,
 49             initialValue=10
 50             )
 51     @GeneratedValue(strategy=GenerationType.TABLE, generator="ID_GENERATOR_1")
 52     @Id
 53     @Column(name="ID")
 54     public Integer getId() {
 55         return id;
 56     }
 57     
 58     /**
 59      * 1、单向一对多的关联关系使用@OneToMany注解进行映射
 60      * 2、利用@JoinColumn来映射外键列的名称
 61      * 3、@OneToMany在默认情况下使用懒加载的检索策略,可以通过fetch=FetchType.EAGER
 62      *    来修改为立即加载策略;
 63      * 4、单向一对多可以删除1的一方,此时JPA的做法是将多的一方的外键全部置为null,然后再删除1的一方
 64      *    可以通过设置cascade={CascadeType.REMOVE}来设置为级联删除(删除1的一方的同时把多的
 65      *    一方也同时删除,还可以设置其它的删除策略)
 66      */
 67     @OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.REMOVE})
 68     @JoinColumn(name="CUSTOMER_ID")
 69     public Set<Order1> getOrders() {
 70         return orders;
 71     }
 72 
 73     public void setOrders(Set<Order1> orders) {
 74         this.orders = orders;
 75     }
 76     
 77     @Column(name="LAST_NAME", length=50, nullable=false)
 78     public String getLastName() {
 79         return lastName;
 80     }
 81     
 82     @Column(name="BIRTHDAY")
 83     @Temporal(TemporalType.DATE)
 84     public Date getBirthday() {
 85         return birthday;
 86     }
 87 
 88     @Column(name="CREATED_TIME", columnDefinition="DATE")
 89     public Date getCreatedTime() {
 90         return createdTime;
 91     }
 92     
 93     @Column(name="EMAIL",columnDefinition="TEXT")
 94     public String getEmail() {
 95         return email;
 96     }
 97     
 98     /*
 99      * 工具方法,不需要映射为数据表的一列
100      */
101     @Transient
102     public String getInfo(){
103         return "lastName: " + lastName + " email: " + email;
104     }
105 
106     @Column(name="AGE")
107     public int getAge() {
108         return age;
109     }
110 
111     @SuppressWarnings("unused")
112     private void setId(Integer id) {
113         this.id = id;
114     }
115 
116     public void setLastName(String lastName) {
117         this.lastName = lastName;
118     }
119 
120     public void setEmail(String email) {
121         this.email = email;
122     }
123 
124     public void setAge(int age) {
125         this.age = age;
126     }
127 
128     public void setBirthday(Date birthday) {
129         this.birthday = birthday;
130     }
131 
132     public void setCreatedTime(Date createdTime) {
133         this.createdTime = createdTime;
134     }
135     
136 }

List_3. 测试代码

 1 package com.magicode.jpa.single.one2many;
 2 
 3 import java.util.Date;
 4 
 5 import javax.persistence.EntityManager;
 6 import javax.persistence.EntityManagerFactory;
 7 import javax.persistence.EntityTransaction;
 8 import javax.persistence.Persistence;
 9 
10 import org.junit.After;
11 import org.junit.Before;
12 import org.junit.Test;
13 
14 public class One2ManyTest {
15     
16     EntityManagerFactory emf = null;
17     EntityManager em = null;
18     EntityTransaction transaction = null;
19     
20     @Before
21     public void before(){
22         emf = Persistence.createEntityManagerFactory("jpa-1");
23         em = emf.createEntityManager();
24         transaction = em.getTransaction();
25         transaction.begin();
26     }
27     
28     @After
29     public void after(){
30         transaction.commit();
31         em.close();
32         emf.close();
33     }
34     
35     @Test
36     public void testPersist(){
37         
38         for(int i = 0; i < 3; i++){
39             char c = (char) ('A' + i);
40             String strName = (" " + c + c).trim();
41             int age = 25 + i;
42             
43             Customer1 customer = new Customer1();
44             customer.setAge(age);
45             customer.setEmail(strName + "@163.com");
46             customer.setLastName(strName);
47             customer.setBirthday(new Date());
48             customer.setCreatedTime(new Date());
49             
50             Order1 order1 = new Order1();
51             order1.setOrderName("O-" + strName + "-1");
52             
53             Order1 order2 = new Order1();
54             order2.setOrderName("O-" + strName + "-2");
55             
56             //设置关联关系
57             customer.getOrders().add(order1);
58             customer.getOrders().add(order2);
59             
60             /**
61              * 保存的顺序没有区别,无论什么顺序都会有update语句发送
62              */
63             em.persist(customer);
64             em.persist(order1);
65             em.persist(order2);
66         }
67     }
68     
69 }
原文地址:https://www.cnblogs.com/lj95801/p/5005789.html