JPA中的一对多双向关联与级联操作
学习Spring有两周时间了 , 个人觉得服务端主要实现的是数据关系的维护和数据结构的制定 , 以及由业务需求产生的CRUD , 只要保证对前端提供的接口稳定高效响应 , 具体的前端实现完全不关心.
这个是接触后端的一个感受 , Spring boot使用了特定的方式来进行配置 ,大大简化了后端开发人员的开发工作量 ,比如JPA:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来 ,此时数据之间的关系维护和数据结构的制定就显得尤为关键 , 下面记录数据表对应关系中的常见关系:一对多关系.
数据表关系
下面用实际场景简单理解数据表之间的关系
一对一:我有一个身份证号 ;
一对多:我有多张银行卡;
多对多:我是招行、交行、建行的客户,但是这些银行用户均过亿。
一对多双向关联
下面以订单order和订单项orderitem来展示
创建订单实体类,代码如下:
package learn.jpa.entity; import java.util.HashSet;
import java.util.Set; import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany; /**
* 订单
*/
@Entity // 定义类为实体类
public class Order { private String orderid;
private float amount = 0f;
private Set<OrderItem> item = new HashSet<OrderItem>(); @Id // 实体标识符,因为是字符串类型,所有不能用 @GeneratedValue,只能人为的赋值
@Column(length=20)
public String getOrderid() {
return orderid;
}
public void setOrderid(String orderid) {
this.orderid = orderid;
}
@Column(nullable = false)
public float getAmount() {
return amount;
}
public void setAmount(float amount) {
this.amount = amount;
}
@OneToMany(cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE})
public Set<OrderItem> getItem() {
return item;
}
public void setItem(Set<OrderItem> item) {
this.item = item;
} }
/**
* 1 - N
* 多的一端为关系维护端,关系维护端负责外键记录的更新
*
*/
创建订单项实体类,代码如下
package learn.jpa.entity; import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id; /**
* 订单项
*/
@Entity // 定义类为实体类
public class OrderItem { private int id;
private String productName;
private float sellPrice = 0f;
private Order order; @Id // 实体标识符
@GeneratedValue // 主键自动增长
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
} @Column(length=40,nullable=false)
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
} @Column(nullable=false)
public float getSellPrice() {
return sellPrice;
}
public void setSellPrice(float sellPrice) {
this.sellPrice = sellPrice;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
注解:
1、@OneToMany(fetch=FetchType,cascade=CascadeType)
@OneToMany描述一个一对多的关联,该属性应该为集体类型,在数据库中并没有实际字段.
fetch:表示该属性的读取策略,有EAGER和LAZY两种,分别表示主支抓取和延迟加载,默认为EAGER.
cascade:表示级联操作策略,对于OneToMany类型的关联非常重要,通常该实体更新或删除时,其关联的实体也应当被更新或删除
(1)、CascadeType.MERGE级联更新:若items属性修改了那么order对象保存时同时修改items里的对象。对应EntityManager的merge方法
(2)、CascadeType.PERSIST级联刷新:获取order对象里也同时也重新获取最新的items时的对象。对应EntityManager的refresh(object)方法有效。即会重新查询数据库里的最新数据
(3)、CascadeType.REFRESH级联保存:对order对象保存时也对items里的对象也会保存。对应EntityManager的presist方法
(4)、CascadeType.REMOVE级联删除:对order对象删除也对items里的对象也会删除。对应EntityManager的remove方法
CascadeType.PERSIST只有A类新增时,会级联B对象新增。若B对象在数据库存(跟新)在则抛异常(让B变为持久态)
CascadeType.MERGE指A类新增或者变化,会级联B对象(新增或者变化)
CascadeType.REMOVE只有A类删除时,会级联删除B类;
CascadeType.ALL包含所有;
综上:大多数情况用CascadeType.MERGE就能达到级联跟新又不报错,用CascadeType.ALL时要斟酌下CascadeType.REMOVE
optional:是否允许该字段为null,该属性应该根据数据库表的外键约束来确定,默认为true
一对多延迟加载与关系维护
订单实体类,代码:
package learn.jpa.entity; 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.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table; /**
* 订单
*/
@Entity // 定义类为实体类
@Table(name="orders")
public class Order { private String orderid;
private float amount = 0f;
private Set<OrderItem> item = new HashSet<OrderItem>(); @Id // 实体标识符,因为是字符串类型,所有不能用 @GeneratedValue,只能人为的赋值
@Column(length=20)
public String getOrderid() {
return orderid;
}
public void setOrderid(String orderid) {
this.orderid = orderid;
}
@Column(nullable = false)
public float getAmount() {
return amount;
}
public void setAmount(float amount) {
this.amount = amount;
}
/**
* 如果是一对多或多对多 fetch 默认是延迟加载,反之是立即加载
* mappedBy="order" 表示由实体 OrderItem 中的 order 属性维护
* @return
*/
@OneToMany(cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE},
fetch=FetchType.LAZY,mappedBy="order")
public Set<OrderItem> getItem() {
return item;
}
public void setItem(Set<OrderItem> item) {
this.item = item;
} public void addOrderItem(OrderItem orderItem){
orderItem.setOrder(this);
this.item.add(orderItem);
} }
/**
* 1 - N
* 多的一端为关系维护端,关系维护端负责外键记录的更新
*
*/
mappedBy只有在双向关联时,才会使用这个属性
mappedBy=”另一方的关系引用属性”
订单项实体类,代码:
package learn.jpa.entity; import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table; /**
* 订单项
*/
@Entity // 定义类为实体类
public class OrderItem { private int id;
private String productName;
private float sellPrice = 0f;
private Order order; @Id // 实体标识符
@GeneratedValue // 主键自动增长
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
} @Column(length=40,nullable=false)
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
} @Column(nullable=false)
public float getSellPrice() {
return sellPrice;
}
public void setSellPrice(float sellPrice) {
this.sellPrice = sellPrice;
}
@ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},fetch=FetchType.EAGER,optional=false)
@JoinColumn(name="order_id")
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
joinColumns属性表示,在保存关系中的表中,所保存关联关系的外键的字段。并配合@JoinColumn标记使用。
小结
理解关联表中存储的关系对含义, 记下使用的套路基本上就没什么问题了 ,下篇文章将记录多对多双向关联与级联操作 .
JPA中的一对多双向关联与级联操作的更多相关文章
- JPA学习---第九节:JPA中的一对多双向关联与级联操作
一.一对多双向关联与级联操作 1.创建项目,配置文件代码如下: <?xml version="1.0" encoding="UTF-8"?> < ...
- JPA学习---第十一节:JPA中的多对多双向关联实体定义与注解设置及操作
1.定义实体类,代码如下: (1).学生实体类: package learn.jpa.entity; import java.util.HashSet; import java.util.Set; i ...
- Hibernate从入门到精通(九)一对多双向关联映射
上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映射,即在一的 ...
- Hibernate(九)一对多双向关联映射
上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关 内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映 射,即在 ...
- Hibernate 一对多双向关联Demo
以Classes[班级]和Student[学生]为例的Demo //Classes.java public class Classes implements Serializable { privat ...
- hibernate 一对多双向关联 详解
一.解析: 1. 一对多双向关联也就是说,在加载班级时,能够知道这个班级所有的学生. 同时,在加载学生时,也能够知道这个学生所在的班级. 2.我们知道,一对多关联映射和多对一关联映射是一样的,都是在 ...
- Hibernate中用注解配置一对多双向关联和多对一单向关联
Hibernate中用注解配置一对多双向关联和多对一单向关联 Hibernate提供了Hibernate Annotations扩展包,使用注解完成映射.在Hibernate3.3之前,需单独下载注解 ...
- SpringData_04_ JPA中的一对多
1.JPA中的一对多 在一对多关系中,我们习惯把一的一方称之为主表,把多的一方称之为从表.在数据库中建立一对多的关系,需要使用数据库的外键约束. 什么是外键? 指的是从表中有一列,取值参照主表的主键, ...
- grails一对多双向关联
前面分享了一些学习grails的心得,可是grails的知识还远不止这些,这次整理了一点有关grails一对多双向关联关系的知识.我认为这样的关联用的地方太多了,这次准备的样例是城市和区域的相关样例. ...
随机推荐
- scriptlet
<!-- <%! %>:可以修饰全局变量.常量.类.方法 对应java类中的成员变量.常量.内部类.成员方法 --> <%! int num=10;//全局变量 publ ...
- IO流-递归遍历目录下指定后缀名结尾的文件名称
/* *自定义遍历目录下指定后缀名结尾文件的名称的方法: * * param file:指定目录 name:指定后缀名 */ 1 public static void FileName(File fi ...
- vue2.0使用记录
父组件给子组件传值[props] 1.首先在父组件的script标签中引入子组件 import Children from './Children' 2.在template内引入子组件 <Chi ...
- 通过adb把apk安装到系统分区
通过adb把apk安装到系统分区 以谷歌拼音为例:GooglePinyin1.4.2.apk提取出so文件libjni_googlepinyinime_4.solibjni_googlepinyini ...
- 关于Google Android平台的ClockworkMod Recovery恢复模式
lockworkMod Recovery,它也被称为Clockwork与CWM,它是装载Google Android操作系统设备的一个自定义的Recovery恢复模式,它可以使得相关Android设备 ...
- IT程序猿们,我该做什么选择呢
这个时刻,我想我遇到人生小拐点了,程序猿到了30岁,到达了一个分界线了,现在的我该何去何从呢? 先谈下简单的情况吧: 来这个公司2年了,之前因为身体的原因,不想那么累,于是选择了一份维护的工作,就来了 ...
- C#的new操作符到底做了什么
使用new操作符来创建对象,其背后到底发生了什么? 有一个父类Animal,Dog派生于Animal. class Program { static void Main(string[] args) ...
- C#程序集系列04,在程序集包含多个module的场景下理解关键字internal
本篇在一个程序集包含多个module的场景下体验internal的含义. →查看F盘as文件夹下的文件→删除MainClass.exe→把MyFirstModule和MySecondModule组装到 ...
- FT项目开发技术点(四)
1.jsp页面form传递过来的值是在后台ishi通过name获得的而非ID.上传文字要用input type=text属性 <tr> <th>品牌:</th> & ...
- RobotFramework自动化2-自定义关键字
前言 有时候一个页面上有多个对象需要操作,如果一个个去定位的话,比较繁琐,这时候就可以定位一组对象.Selenium2library提供了Get Webelements 关键字,用于定位一组元素 以百 ...