jpa级联添加_JPA中的一对多双向关联与级联操作

学习Spring有两周时间了 , 个人觉得服务端主要实现的是数据关系的维护和数据结构的制定 , 以及由业务需求产生的CRUD , 只要保证对前端提供的接口稳定高效响应 , 具体的前端实现完全不关心.

这个是接触后端的一个感受 , Spring boot使用了特定的方式来进行配置 ,大大简化了后端开发人员的开发工作量 ,比如JPA:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来 ,此时数据之间的关系维护和数据结构的制定就显得尤为关键 , 下面记录数据表对应关系中的常见关系:一对多关系.

数据表关系

下面用实际场景简单理解数据表之间的关系

一对一:我有一个身份证号 ;

一对多:我有多张银行卡;

多对多:我是招行、交行、建行的客户,但是这些银行用户均过亿。

一对多双向关联

下面以订单order和订单项orderitem来展示

创建订单实体类,代码如下:

packagelearn.jpa.entity;importjava.util.HashSet;importjava.util.Set;importjavax.persistence.CascadeType;importjavax.persistence.Column;importjavax.persistence.Entity;importjavax.persistence.Id;importjavax.persistence.OneToMany;/*** 订单*/@Entity//定义类为实体类

public classOrder {privateString orderid;private float amount =0f;private Set item = new HashSet();

@Id//实体标识符,因为是字符串类型,所有不能用 @GeneratedValue,只能人为的赋值

@Column(length=20)publicString getOrderid() {returnorderid;

}public voidsetOrderid(String orderid) {this.orderid =orderid;

}

@Column(nullable= false)public floatgetAmount() {returnamount;

}public void setAmount(floatamount) {this.amount =amount;

}

@OneToMany(cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE})public SetgetItem() {returnitem;

}public void setItem(Setitem) {this.item =item;

}

}/*** 1 - N

* 多的一端为关系维护端,关系维护端负责外键记录的更新

**/

创建订单项实体类,代码如下

packagelearn.jpa.entity;importjavax.persistence.Column;importjavax.persistence.Entity;importjavax.persistence.GeneratedValue;importjavax.persistence.Id;/*** 订单项*/@Entity//定义类为实体类

public classOrderItem {private intid;privateString productName;private float sellPrice =0f;privateOrder order;

@Id//实体标识符

@GeneratedValue //主键自动增长

public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}

@Column(length=40,nullable=false)publicString getProductName() {returnproductName;

}public voidsetProductName(String productName) {this.productName =productName;

}

@Column(nullable=false)public floatgetSellPrice() {returnsellPrice;

}public void setSellPrice(floatsellPrice) {this.sellPrice =sellPrice;

}publicOrder getOrder() {returnorder;

}public voidsetOrder(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

一对多延迟加载与关系维护

订单实体类,代码:

packagelearn.jpa.entity;importjava.util.HashSet;importjava.util.Set;importjavax.persistence.CascadeType;importjavax.persistence.Column;importjavax.persistence.Entity;importjavax.persistence.FetchType;importjavax.persistence.Id;importjavax.persistence.OneToMany;importjavax.persistence.Table;/*** 订单*/@Entity//定义类为实体类

@Table(name="orders")public classOrder {privateString orderid;private float amount =0f;private Set item = new HashSet();

@Id//实体标识符,因为是字符串类型,所有不能用 @GeneratedValue,只能人为的赋值

@Column(length=20)publicString getOrderid() {returnorderid;

}public voidsetOrderid(String orderid) {this.orderid =orderid;

}

@Column(nullable= false)public floatgetAmount() {returnamount;

}public void setAmount(floatamount) {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 SetgetItem() {returnitem;

}public void setItem(Setitem) {this.item =item;

}public voidaddOrderItem(OrderItem orderItem){

orderItem.setOrder(this);this.item.add(orderItem);

}

}/*** 1 - N

* 多的一端为关系维护端,关系维护端负责外键记录的更新

**/

mappedBy只有在双向关联时,才会使用这个属性

mappedBy=”另一方的关系引用属性”

订单项实体类,代码:

packagelearn.jpa.entity;importjavax.persistence.CascadeType;importjavax.persistence.Column;importjavax.persistence.Entity;importjavax.persistence.FetchType;importjavax.persistence.GeneratedValue;importjavax.persistence.Id;importjavax.persistence.JoinColumn;importjavax.persistence.ManyToOne;importjavax.persistence.Table;/*** 订单项*/@Entity//定义类为实体类

public classOrderItem {private intid;privateString productName;private float sellPrice =0f;privateOrder order;

@Id//实体标识符

@GeneratedValue //主键自动增长

public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}

@Column(length=40,nullable=false)publicString getProductName() {returnproductName;

}public voidsetProductName(String productName) {this.productName =productName;

}

@Column(nullable=false)public floatgetSellPrice() {returnsellPrice;

}public void setSellPrice(floatsellPrice) {this.sellPrice =sellPrice;

}

@ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},fetch=FetchType.EAGER,optional=false)

@JoinColumn(name="order_id")publicOrder getOrder() {returnorder;

}public voidsetOrder(Order order) {this.order =order;

}

}

joinColumns属性表示,在保存关系中的表中,所保存关联关系的外键的字段。并配合@JoinColumn标记使用。

小结

理解关联表中存储的关系对含义, 记下使用的套路基本上就没什么问题了 ,下篇文章将记录多对多双向关联与级联操作 .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值