JPA学习---第九节:JPA中的一对多双向关联与级联操作
一、一对多双向关联与级联操作
1、创建项目,配置文件代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<!--
name属性用于定义持久化单元的名字 (name必选,空值也合法);
transaction-type 指定事务类型(可选)
-->
<persistence-unit name="learn_jpa" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!-- hibernate.dialect 指定数据库的方言 -->
<!-- <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
<property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/>
<property name="hibernate.connection.username" value="learn_orcl"/>
<property name="hibernate.connection.password" value="learn_orcl"/>
<property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:learn_data?useUnicode=true&characterEncoding=UTF-8"/>
<property name="hibernate.hbm2ddl.auto" value="update"/> -->
<!-- hibernate.hbm2ddl.auto参数的作用主要用于:自动创建|更新|验证数据库表结构 -->
<!--
create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,
哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),
以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。
要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,
但是会插入新值。
--> <properties>
<!-- 数据库方言 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<!-- 数据库驱动 -->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<!-- 数据库用户名 -->
<property name="hibernate.connection.username" value="root" />
<!-- 数据库密码 -->
<property name="hibernate.connection.password" value="123456" />
<!-- 数据库连接URL -->
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/learn_jpa?useUnicode=true&characterEncoding=UTF8"/>
<!-- 最大抓取深度 -->
<property name="hibernate.max_fetch_depth" value="3" />
<!-- 更新方式创建库表 -->
<property name="hibernate.hbm2ddl.auto" value="update" />
<!-- 显示SQL -->
<property name="hibernate.show_sql" value="false" />
<!-- 格式SQL -->
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
2、创建订单实体类,代码如下:
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
* 多的一端为关系维护端,关系维护端负责外键记录的更新
*
*/
3、创建订单项实体类,代码如下:
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
二、JPA中的一对多延迟加载与关系维护
1、订单实体类,代码:
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=”另一方的关系引用属性”
2、订单项实体类,代码:
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标记使用。
3、测试保存,代码如下:
package learn.jpa.test; import static org.junit.Assert.*; import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence; import learn.jpa.entity.Order;
import learn.jpa.entity.OrderItem; import org.junit.Test; public class OneToManyTest { /**
* 测试数据库是否可以生成表
*/
@Test
public void test() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("learn_jpa");
factory.close();
} @Test
public void save(){
EntityManagerFactory factory = Persistence.createEntityManagerFactory("learn_jpa");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin(); // 开启事务
Order order = new Order();
order.setAmount(56f);
order.setOrderid("SE001"); OrderItem item1 = new OrderItem();
item1.setProductName("足球");
item1.setSellPrice(32f); OrderItem item2 = new OrderItem();
item2.setProductName("羽毛球");
item2.setSellPrice(24f); order.addOrderItem(item1);
order.addOrderItem(item2); em.persist(order);
em.getTransaction().commit();
em.close();
factory.close();
}
}
JPA学习---第九节:JPA中的一对多双向关联与级联操作的更多相关文章
- JPA中的一对多双向关联与级联操作
学习Spring有两周时间了 , 个人觉得服务端主要实现的是数据关系的维护和数据结构的制定 , 以及由业务需求产生的CRUD , 只要保证对前端提供的接口稳定高效响应 , 具体的前端实现完全不关心. ...
- JPA学习笔记1——JPA基础
1.JPA简介: Java持久化规范,是从EJB2.x以前的实体Bean(Entity bean)分离出来的,EJB3以后不再有实体bean,而是将实体bean放到JPA中实现.JPA是sun提出的一 ...
- python学习第九讲,python中的数据类型,字符串的使用与介绍
目录 python学习第九讲,python中的数据类型,字符串的使用与介绍 一丶字符串 1.字符串的定义 2.字符串的常见操作 3.字符串操作 len count index操作 4.判断空白字符,判 ...
- JPA学习笔记1——JPA基础 (转自CSDN)
http://blog.csdn.net/chjttony/article/details/6086298 1.JPA简介: Java持久化规范,是从EJB2.x以前的实体Bean(Entity be ...
- 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之前,需单独下载注解 ...
随机推荐
- Windowsphone本地应用信息与市场信息的获取
本地信息都存放在 WMAppManifest 里面,获取就不用说了...知道位置 就知道怎么获取了.. 主要是讲那个 市场上面的详情怎么获取,就是API调用显示在这个页面里面的详情: public v ...
- HLS入门收集(1)
使用HLS各种问题 关于求指数函数 exp(x) 在HLS中使用exp(x),也就是指数函数.不能导出RTL到EDK也就是Pcore 只能导出为VIVADO IP:相关解释:见官方论坛 http:/ ...
- HTML中Meta属性http-equiv="X-UA-Compatible"详解
HTML下head中的http-equiv="X-UA-Compatible"详解: X-UA-Compatible是针对IE8新加的一个设置,对于IE8之外的浏览器是不识别的,这 ...
- Web Service无法加载协定为“ServiceReference1.xxxxxx”的终结点配置部分,因为找到了该协定的多个终结点配置。请按名称指示首选的终结点配置部分
Web Service 无法加载协定为“ServiceReference1.xxxxxx”的终结点配置部分,因为找到了该协定的多个终结点配置.请按名称指示首选的终结点配置部分 原因是在web.co ...
- css3干货
CSS3是CSS2的升级版本,3只是版本号,它在CSS2.1的基础上增加了很多强大的新功能. 目前主流浏览器chrome.safari.firefox.opera.甚至360都已经支持了CSS3大部分 ...
- PHP MYSQLI中事务处理
MYSQL事务处理让所有sql语句执行成功后才去处理,如果有一条没有成功或者报错就会回滚事务,防止敏感操作处理失败.MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其它类型是不支持的 ...
- js浏览器各种位置检测
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 搭通自己的电脑与GitHub的传输通道
一.远程仓库怎么玩 1. 自己搭建一个运行Git的服务器 Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上,但肯定有一台机器有着最原始的版本库,然后别的机器来克隆这个原始版本库,这 ...
- spark概论,补充
基本概念 RDD spark最大的亮点是提出RDD(Resilient Distributed Dataset)的概念,也就是可伸缩的分布式数据集合,本身只读,可恢复.spark本身不做物理储存,通过 ...
- 清理文件默认打开方式.bat
@echo offsetlocal enabledelayedexpansionset "ext=%~x1":loopif defined ext set "ext=!e ...