7、单向一对多的关联关系(1的一方有n的一方的集合属性,n的一方却没有1的一方的引用)
单向一对多的关联关系
具体体现:1的一方有n的一方的集合的引用,n的一方却没有1的一方的引用
举个例子:顾客Customer对订单Order是一个单向一对多的关联关系。Customer一方有对Order的集合的引用。而Order却没有对Customer的引用;
“一对多”的物理意义就是:一个客户可以有多个订单,而一个订单只能归属于一个客户。
“单向”的物理意义就是:客户知道自己有哪些订单,但是订单却不知道自己属于哪个客户(这个容易让人接受一点儿!!!但是,不满足某些业务需求)
同样的,下面看看“单向一对多”的“Customer对Order”会有什么变化:
Order实体的属性(Order中没有对Customer的引用):
@Table(name="t_single_one2many_order")
@Entity
public class Order1 { private Integer id;
private String orderName; //省略getter、setter方法...
}
Customer实体的属性(Customer中有对Order的集合的引用):
@Table(name="t_single_one2many_customer")
@Entity
public class Customer1 { private Integer id;
private String lastName; private String email;
private int age; private Date birthday; private Date createdTime; //Customer1中有对Order1的集合引用
private Set<Order1> orders = new HashSet<Order1>();
//省略getter、setter方法...
}
映射单向一对多的关联关系有两个要点:
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的一方的引用,不需要做任何关于映射的注解)
package com.magicode.jpa.single.one2many; import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TableGenerator; @Table(name="t_single_one2many_order")
@Entity
public class Order1 { private Integer id;
private String orderName; @TableGenerator(name="order_id_generator_1",
table="t_id_generator",
pkColumnName="PK_NAME",
pkColumnValue="seedId_t_order_1",
valueColumnName="PK_VALUE",
initialValue=0,
allocationSize=20)
@GeneratedValue(generator="order_id_generator_1", strategy=GenerationType.TABLE)
@Id
@Column(name="ID")
public Integer getId() {
return id;
} @Column(name="ORDER_NAME")
public String getOrderName() {
return orderName;
} @SuppressWarnings("unused")
private void setId(Integer id) {
this.id = id;
} public void setOrderName(String orderName) {
this.orderName = orderName;
} }
Order1.java作为n的一方不需要任何关于映射的注解
List_2. Customer1实体的代码(包含有对n的一方的集合的引用)
package com.magicode.jpa.single.one2many; import java.util.Date;
import java.util.HashSet;
import java.util.Set; import javax.persistence.CascadeType;
import javax.persistence.Column;
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.OneToMany;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
//import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient; /**
* @Entity 用于注明该类是一个实体类
* @Table(name="t_customer") 表明该实体类映射到数据库的 t_customer 表
*/
@Table(name="t_single_one2many_customer")
@Entity
public class Customer1 { private Integer id;
private String lastName; private String email;
private int age; private Date birthday; private Date createdTime; private Set<Order1> orders = new HashSet<Order1>();
@TableGenerator(name="ID_GENERATOR_1",
table="t_id_generator",
pkColumnName="PK_NAME",
pkColumnValue="seedId_t_customer_1",
valueColumnName="PK_VALUE",
allocationSize=20,
initialValue=10
)
@GeneratedValue(strategy=GenerationType.TABLE, generator="ID_GENERATOR_1")
@Id
@Column(name="ID")
public Integer getId() {
return id;
} /**
* 1、单向一对多的关联关系使用@OneToMany注解进行映射
* 2、利用@JoinColumn来映射外键列的名称
* 3、@OneToMany在默认情况下使用懒加载的检索策略,可以通过fetch=FetchType.EAGER
* 来修改为立即加载策略;
* 4、单向一对多可以删除1的一方,此时JPA的做法是将多的一方的外键全部置为null,然后再删除1的一方
* 可以通过设置cascade={CascadeType.REMOVE}来设置为级联删除(删除1的一方的同时把多的
* 一方也同时删除,还可以设置其它的删除策略)
*/
@OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.REMOVE})
@JoinColumn(name="CUSTOMER_ID")
public Set<Order1> getOrders() {
return orders;
} public void setOrders(Set<Order1> orders) {
this.orders = orders;
} @Column(name="LAST_NAME", length=50, nullable=false)
public String getLastName() {
return lastName;
} @Column(name="BIRTHDAY")
@Temporal(TemporalType.DATE)
public Date getBirthday() {
return birthday;
} @Column(name="CREATED_TIME", columnDefinition="DATE")
public Date getCreatedTime() {
return createdTime;
} @Column(name="EMAIL",columnDefinition="TEXT")
public String getEmail() {
return email;
} /*
* 工具方法,不需要映射为数据表的一列
*/
@Transient
public String getInfo(){
return "lastName: " + lastName + " email: " + email;
} @Column(name="AGE")
public int getAge() {
return age;
} @SuppressWarnings("unused")
private void setId(Integer id) {
this.id = id;
} public void setLastName(String lastName) {
this.lastName = lastName;
} public void setEmail(String email) {
this.email = email;
} public void setAge(int age) {
this.age = age;
} public void setBirthday(Date birthday) {
this.birthday = birthday;
} public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
} }
List_3. 测试代码
package com.magicode.jpa.single.one2many; import java.util.Date; import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence; import org.junit.After;
import org.junit.Before;
import org.junit.Test; public class One2ManyTest { EntityManagerFactory emf = null;
EntityManager em = null;
EntityTransaction transaction = null; @Before
public void before(){
emf = Persistence.createEntityManagerFactory("jpa-1");
em = emf.createEntityManager();
transaction = em.getTransaction();
transaction.begin();
} @After
public void after(){
transaction.commit();
em.close();
emf.close();
} @Test
public void testPersist(){ for(int i = 0; i < 3; i++){
char c = (char) ('A' + i);
String strName = (" " + c + c).trim();
int age = 25 + i; Customer1 customer = new Customer1();
customer.setAge(age);
customer.setEmail(strName + "@163.com");
customer.setLastName(strName);
customer.setBirthday(new Date());
customer.setCreatedTime(new Date()); Order1 order1 = new Order1();
order1.setOrderName("O-" + strName + "-1"); Order1 order2 = new Order1();
order2.setOrderName("O-" + strName + "-2"); //设置关联关系
customer.getOrders().add(order1);
customer.getOrders().add(order2); /**
* 保存的顺序没有区别,无论什么顺序都会有update语句发送
*/
em.persist(customer);
em.persist(order1);
em.persist(order2);
}
} }
7、单向一对多的关联关系(1的一方有n的一方的集合属性,n的一方却没有1的一方的引用)的更多相关文章
- JPA(六):映射关联关系------映射单向一对多的关联关系
映射单向一对多的关联关系 新建项目项目请参考<JPA(二):HellWord工程>,基于上一章讲解的<JPA(五):映射关联关系------映射单向多对一的关联关系>中的例子进 ...
- JPA中实现单向一对多的关联关系
场景 JPA入门简介与搭建HelloWorld(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103473937 ...
- JPA 单向一对多关联关系
映射单向一对多的关联关系 1.首先在一的一端加入多的一端的实体类集合 2.使用@OneToMany 来映射一对多的关联关系3.使用@JoinColumn 来映射外键列的名称4.可以使用@OneToMa ...
- 6、JPA_映射单向多对一的关联关系(n的一方有1的引用,1的一方没有n的集合属性)
单向多对一的关联关系 具体体现:n的一方有1的引用,1的一方没有n的集合属性 举个例子:订单Order对顾客Customer是一个单向多对一的关联关系.Order是n的一方,有对Customer的引用 ...
- JPA中实现双向一对多的关联关系
场景 JPA入门简介与搭建HelloWorld(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103473937 ...
- 8、双向一对多的关联关系(等同于双向多对一。1的一方有对n的一方的集合的引用,同时n的一方有对1的一方的引用)
双向一对多关联关系 “双向一对多关联关系”等同于“双向多对一关联关系”:1的一方有对n的一方的集合的引用,同时n的一方有对1的一方的引用. 还是用客户Customer和订单Order来解释: “一对多 ...
- Hibernate5.2关联关系之单向一对多(一)
Hibernate5.2之单向一对多 一. 简介 Hibernate中最复杂的应该就是各种关联(单向一对多.单向多对一.双向一对多.一对一.多对多)关系的映射,于是笔者就想着去写一些关于Hibe ...
- (十一)Hibernate中的多表操作(1):单向一对多
一.单向一对多() 案例一(用XML文件配置): 一个班级有多个学生,班级可以查看所有学生的信息. ClassBean.java package bean; import java.util.Hash ...
- jpa单向一对多
单向一对多是一个类中的一条记录可对应另一个类的多条记录: 比如一个部门可对应多个员工: jpa中的实现步骤: one-to-many的one类中添加一个many类类型的set;比如部门类D ...
随机推荐
- TLV格式是什么格式
TLV 格式是什么格式 一种可变格式, TLV 的意思就是: Type 类型, Lenght 长度, Value 值: Type 和 Length 的长度固定,一般那是 2 . 4 个字节: Valu ...
- mac os使用homebrew来管理后台服务
在linux下我们经常通过 service 或者 /etc/init.d/来管理我们的后台服务软件,并使用包管理器安装这些软件. 在mac下有homebrew这个好用的工具来安装软件,但是一直没有找到 ...
- XCODE快捷键和功能汇总篇(不断更新)
快捷键 command+b(build) 编译 command+r(run) 运行编译后程序鼠标放在代码元素上,按command然后单击,可以看到元素的属性
- PHP中如何获取多个checkbox的值
> > > weeks后的中括号不可漏,否则用PHP获取的时候只能取到最后一个值.之后PHP就很好处理了,如下: PHP获取checkbox值方法一: $weeks = $_POST ...
- c#之反射总结
1.了解什么事程序集 2.加载程序集 首先要加载需要加载的程序集,然后找到指定的类型,进而往下进行动态加载. 要加载的程序集中的内容: public class Class1:Person { pr ...
- IIS7.5 HTTP 错误 500.19 - Internal Server Error 问题的解决方案
昨天在 windows 7 下用 IIS 7.5 运行一个以前用 .NET Framework 3.5 写的项目,发现总是出现 500.19 错误,如下: 百度了好久,没找到解决问题确切的答案,我也知 ...
- Android使用XML做动画UI
在Android应用程序,使用动画效果,能带给用户更好的感觉.做动画可以通过XML或Android代码.本教程中,介绍使用XML来做动画.在这里,介绍基本的动画,如淡入,淡出,旋转等. 效果: htt ...
- MySQL性能优化的最佳20+条经验(转)
今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我 们程序员需要去关注的事情.当我们去设计数据库表结构,对操作数 ...
- POJ 2155 Matrix (二维线段树入门,成段更新,单点查询 / 二维树状数组,区间更新,单点查询)
题意: 有一个n*n的矩阵,初始化全部为0.有2中操作: 1.给一个子矩阵,将这个子矩阵里面所有的0变成1,1变成0:2.询问某点的值 方法一:二维线段树 参考链接: http://blog.csdn ...
- JsRender系列demo(2)多模板-template
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...