一、一对多双向关联与级联操作

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&amp;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&amp;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中的一对多双向关联与级联操作的更多相关文章

  1. JPA中的一对多双向关联与级联操作

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

  2. JPA学习笔记1——JPA基础

    1.JPA简介: Java持久化规范,是从EJB2.x以前的实体Bean(Entity bean)分离出来的,EJB3以后不再有实体bean,而是将实体bean放到JPA中实现.JPA是sun提出的一 ...

  3. python学习第九讲,python中的数据类型,字符串的使用与介绍

    目录 python学习第九讲,python中的数据类型,字符串的使用与介绍 一丶字符串 1.字符串的定义 2.字符串的常见操作 3.字符串操作 len count index操作 4.判断空白字符,判 ...

  4. JPA学习笔记1——JPA基础 (转自CSDN)

    http://blog.csdn.net/chjttony/article/details/6086298 1.JPA简介: Java持久化规范,是从EJB2.x以前的实体Bean(Entity be ...

  5. Hibernate从入门到精通(九)一对多双向关联映射

    上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映射,即在一的 ...

  6. Hibernate(九)一对多双向关联映射

    上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关 内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映 射,即在 ...

  7. Hibernate 一对多双向关联Demo

    以Classes[班级]和Student[学生]为例的Demo //Classes.java public class Classes implements Serializable { privat ...

  8. hibernate 一对多双向关联 详解

    一.解析: 1.  一对多双向关联也就是说,在加载班级时,能够知道这个班级所有的学生. 同时,在加载学生时,也能够知道这个学生所在的班级. 2.我们知道,一对多关联映射和多对一关联映射是一样的,都是在 ...

  9. Hibernate中用注解配置一对多双向关联和多对一单向关联

    Hibernate中用注解配置一对多双向关联和多对一单向关联 Hibernate提供了Hibernate Annotations扩展包,使用注解完成映射.在Hibernate3.3之前,需单独下载注解 ...

随机推荐

  1. JS基础学习1——什么是基础js类和原型?

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. Oracle 11g 客户端 下载地址

    摘自: http://blog.csdn.net/davidhsing/article/details/8271845 Oracle Database Instant Client 11g 11.2. ...

  3. Overcome the Dilemma of "unlock" and "trust"

    When examining an Android phone, we have to overcome some barriers first so that we could extract da ...

  4. RPC通信(Windows版、Android版)

    1.RPC通信模型 2.调用截图 服务器端 PC客户端: Android客户端: 3.remotetea jrpcgen.jar:生成Java源文件 oncrpc.jar:框架通信调用 portmap ...

  5. box2d 遍历世界中 body 的方法

    大家都知道,循环遍历有很多方法,在box2d中大家普遍使用while和for循环来遍历世界,那什么时候使用for,什么时候使用while呢? 当循环中不设计body删除的时候,使用for循环,即: C ...

  6. (五)、nodejs使用bootstrap的样式进行分页

    一.page方法 /****************************************************** * Created User: * Created Time: 201 ...

  7. Curses library not found. Please install appropriate package

    今天安装mysql-5.5.3-m3的时候,报下面的错误: -- Could NOT find OpenSSL (missing: OPENSSL_LIBRARIES OPENSSL_INCLUDE_ ...

  8. 关于SQL表联接

    以SQL2008为例,Microsoft SQL Server 2008支持四种表运算符-JOIN,APPLY,PIVOT,UNPIVOT.JOIN表运算符是ANSI标准,而其他三种是T-SQL对标准 ...

  9. luigi学习6--parameters详解

    parameter就好比是一个task的构造方法.luigi要求你在类的scope上定义parameter. 如下面就是一个定义parameter的例子: class DailyReport(luig ...

  10. Tomcat配置虚拟主机后的登录验证码问题

    先描述一下问题现象,在本地测试运行一个java web网站,一切正常.但把网站部署到Linux服务器上后,发现登录出了问题,提示验证码输入不正确.登录时需要输入验证码,而验证码的原值是先存入sessi ...