JPA的一对多映射(双向)关联
实体Customer:用户。
实体Order:订单。
Customer和Order是一对多关系。那么在JPA中,如何表示一对多的双向关联呢?
JPA使用@OneToMany和@ManyToOne来标识一对多的双向关联。一的一端(Customer)使用@OneToMany,多端(Order)使用@ManyToOne。
在JPA规范中,一对多的双向关系由多端(Order)来维护。就是说多端(Order)为关系维护端,负责关系的增删改查。一端(Customer)则为关系被维护端,不能维护关系。
一端(Customer)@OneToMany注释的mappedBy="customer"属性表明Customer是关系被维护端。
多端(Order)使用@ManyToOne和@JoinColumn来注释属性CUSTOMER_ID,@ManyToOne表明Order是多端,@JoinColumn设置在Order表中的关联字段(外键)。
Customer实体类如下:
/**
*数据库持久化类
* @author z
*
*/
@Table(name="JPA_CUSTOMERS")//主要是映射表名对应的数据库表名JPA_CUSTOMER默认情况下可以不写表名与持久化类名相同
@Entity //表明这是一个持久化类
public class Customer { private Integer id;
private String lastName;
private String email;
private int age ; private Date createdTime;
private Date birth; /**
* 单向一对多关系映射
* 1、添加多的一方的集合属性
*/
private Set<Order> orders=new HashSet<>(); /**
* 定义各数据列必须加在get方法上
* @return
*/
//定义主键,生成主键的策略AUTO自动的根据数据的类型生成主键
@GeneratedValue(strategy=GenerationType.AUTO)
@Id //定义数据列
// @Column(name="ID")//定义数据库的列名如果与字段名一样可以省略 //使用table生成主键
// @TableGenerator(name="ID_GENERATOR",
// table="JPA_ID_GENERATORS",
// pkColumnName="PK_NAME",
// pkColumnValue="CUSTOMER_ID",
// valueColumnName="PK_VALUE",
// allocationSize=100
//
//
// )
//
// @GeneratedValue(strategy=GenerationType.TABLE,generator="ID_GENERATOR")
// @Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
} @Column(name="LAST_NAME",length=,nullable=false) //nullable false表示此字段不能为空
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
} @Temporal(TemporalType.TIMESTAMP)
public Date getCreatedTime() {
return createdTime;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
@Temporal(TemporalType.DATE)
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
} //映射单向一对多的关联关系
//使用@OneToMany 来映射一对多的关联关系
//使用@JoinColumn 来映射外键列的名称
//可以使用@OneToMany的fetch 属性来修改默认的加载策略
//可以通过@OneToMany的cascade 属性来修改默认的删除策略
//cascade={CascadeType.REMOVE} 会把主表和从表的数据都删除
//mappedBy表明放弃关联关系维护并且不能在使用
//注意:若在一的一端@oneToMany 中使用mapperBy属性,则@oneToMany端就不能在使用@JoinColumn(name="CUSTOMER_ID")属性
// @JoinColumn(name="CUSTOMER_ID")
@OneToMany(fetch=FetchType.EAGER,cascade={CascadeType.REMOVE},mappedBy="customer")
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
} //工具方法,不需要映射为数据表的一列
@Transient
public String getInfo(){
return "lastName:"+lastName+",email:"+email;
}
@Override
public String toString() {
return "Customer [id=" + id + ", lastName=" + lastName + ", email=" + email + ", age=" + age + ", createdTime="
+ createdTime + ", birth=" + birth + "]";
} }
多的一端实体类Order如下:
/**
* 单向多对一
* 一个订单可以有多个用户
* 一个用户可以有多个订单
* @author z
*
*/
@Table(name="JPA_ORDERS")
@Entity
public class Order {
private Integer id;
private String orderName; private Customer customer;
@GeneratedValue//使用默认的主键生成方式
@Id
public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
}
@Column(name="ORDER_NAME")
public String getOrderName() {
return orderName;
} public void setOrderName(String orderName) {
this.orderName = orderName;
}
//映射单向n-1的关联关系
//使用@ManyToOne 来映射多对一的关系
//使用@JoinColumn 来映射外键
//可以使用@ManyToOne的fetch属性来修改默认的关联属性的加载策略
@JoinColumn(name="CUSTOMER_ID")//外键列的列名
@ManyToOne(fetch=FetchType.LAZY)
public Customer getCustomer() {
return customer;
} public void setCustomer(Customer customer) {
this.customer = customer;
} @Override
public String toString() {
return "Order [id=" + id + ", orderName=" + orderName + ", customer=" + customer+ "]";
} }
简单的测试类
public class JPATest {
private EntityManagerFactory entityManagerFactory;
private EntityManager entityManager;
private EntityTransaction transaction;
@Before
public void init(){
entityManagerFactory= Persistence.createEntityManagerFactory("jpa-1");
entityManager=entityManagerFactory.createEntityManager();
transaction=entityManager.getTransaction();
transaction.begin();//开启事务 }
@After
public void destroy(){
transaction.commit();
entityManager.close();
entityManagerFactory.close();
} //修改
@Test
public void testUpdate(){
Customer customer=entityManager.find(Customer.class, );
customer.getOrders().iterator().next().setOrderName("O-XXX-10"); } //删除
//默认情况下,若删除1的一端,则会先把关联的多的一段的外键置空,然后删除一的一端
////可以通过@OneToMany的cascade 属性来修改默认的删除策略
@Test
public void testOneToManyRemove(){
Customer customer=entityManager.find(Customer.class, );
entityManager.remove(customer); } //默认对关联多的一方使用懒加载的加载策略(延迟加载)
//可以使用@OneToMany的fetch 属性来修改默认的加载策略
//查询
@Test
public void testOneToManyFind(){
Customer customer=entityManager.find(Customer.class,);
System.out.println(customer.getLastName()); System.out.println(customer.getOrders().size()); } //双向一对多的关联关系在执行保存时
//若先保存多的一端,在保存一的一端,默认情况下,会多出四条update语句
//若先保存一的一端则会多出2(n)条update语句
//在进行双向一对多的关联关系时,建议使用多的一方来维护关联关系,而1的一方不维护关联关系,这样会有效的减少sql语句
//注意:若在一的一端@oneToMany 中使用mapperBy属性,则@oneToMany端就不能在使用@JoinColumn(name="CUSTOMER_ID")属性//保存
@Test
public void testOneToManyPersist(){
Customer customer=new Customer();
customer.setAge();
customer.setBirth(new Date());
customer.setCreatedTime(new Date());
customer.setEmail("CC@163.com");
customer.setLastName("AA"); Order order1=new Order();
order1.setOrderName("o-CC-1"); Order order2=new Order();
order2.setOrderName("o-CC-2"); //建立关联关系
customer.getOrders().add(order1);
customer.getOrders().add(order2);
//执行保存操作
entityManager.persist(customer);
entityManager.persist(order1);
entityManager.persist(order2); }
}
源码地址:https://github.com/wuhongpu/JPA.git
JPA的一对多映射(双向)关联的更多相关文章
- JPA学习---第九节:JPA中的一对多双向关联与级联操作
一.一对多双向关联与级联操作 1.创建项目,配置文件代码如下: <?xml version="1.0" encoding="UTF-8"?> < ...
- 【Hibernate步步为营】--(一对多映射)之双向关联
上篇文章讨论了单向关联的一对多映射,在一的一端维护双向的关系这样的做法尽管能实现可是存在非常多缺陷,首先生成非常多多余的SQL语句,由于多的一端不维护关系,仅仅有一的一端维护,在进行操作时一的一端会发 ...
- JPA中的一对多双向关联与级联操作
学习Spring有两周时间了 , 个人觉得服务端主要实现的是数据关系的维护和数据结构的制定 , 以及由业务需求产生的CRUD , 只要保证对前端提供的接口稳定高效响应 , 具体的前端实现完全不关心. ...
- Hibernate从入门到精通(九)一对多双向关联映射
上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映射,即在一的 ...
- Hibernate(九)一对多双向关联映射
上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关 内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映 射,即在 ...
- JPA中实现双向多对多的关联关系(附代码下载)
场景 JPA入门简介与搭建HelloWorld(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103473937 ...
- hibernate多对一双向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- hibernate一对一外键双向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- hibernate一对一主键双向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
随机推荐
- Java定时任务调度详解
前言 在实际项目开发中,除了Web应用.SOA服务外,还有一类不可缺少的,那就是定时任务调度.定时任务的场景可以说非常广泛,比如某些视频网站,购买会员后,每天会给会员送成长值,每月会给会员送一些电影券 ...
- ng-options的使用
参考:官方文档.zhx1991 select 无默认选择一项 <select name="" id="" class="form-control ...
- 再起航,我的学习笔记之JavaScript设计模式25(迭代器模式)
迭代器模式 概念介绍 迭代器模式(Iterator): 在不暴露对象内部结构的同时,可以顺序地访问聚合对象内部的元素. 迭代器 程序中的循环是一种利器,循环语句也使我们程序开发更简洁高效,但是有时一遍 ...
- 在web中使用HTTPS
背景 目前网上流行的是HTTP协议,HTTPS协议还在逐步推广的过程中. HTTP协议以明文发送内容,容易被攻击者窃听.HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份[ ...
- [err] 1055
本人mysql安装在ubuntu16.04上,mysql版本是5.7.19:在创建表和插入数据时报了 [Err] 1055 - Expression #1 of ORDER BY clause is ...
- JavaScript遍历对象-总结一
原生JavaScript 遍历 1.for 循环遍历 let array1 = ['a','b','c']; for (let i = 0;i < array1.length;i++){ con ...
- PyTorch教程之Training a classifier
我们已经了解了如何定义神经网络,计算损失并对网络的权重进行更新. 接下来的问题就是: 一.What about data? 通常处理图像.文本.音频或视频数据时,可以使用标准的python包将数据加载 ...
- 实例讲解webpack的基本使用第三篇
这一篇来讲解一下webpack的htmlWebpackHtml插件的使用. 先来思考一个实际问题:我们现在在index.html引用的js文件是写死的.但是我们每次打包后的文件都是动态的,那么我们怎么 ...
- bzoj3224 普通平衡树(c++vector)
Tyvj 1728 普通平衡树 2014年8月23日6,4365 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有 ...
- Ubuntu16.04 install OpenJDK8
1.按Ctrl + Alt + T打开终端.打开后,运行下面的命令来添加PPA:sudo add-apt-repository ppa:openjdk-r/ppa2.之后,更新系统包缓存并安装Open ...