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 ...
随机推荐
- Bootstrap中的strong和em强调标签
在Bootstrap中除了使用标签<strong>.<em>等说明正文某些字词.句子的重要性,Bootstrap还定义了一套类名,这里称其为强调类名(类似前面说的“.lead” ...
- PHP防SQL注入攻击
PHP防SQL注入攻击 收藏 没有太多的过滤,主要是针对php和mysql的组合. 一般性的防注入,只要使用php的 addslashes 函数就可以了. 以下是一段copy来的代码: PHP代码 $ ...
- ThinkPHP控制器输出防止乱码小技巧
在控制器中加一句:试试看 header('content-type:text/html;charset=utf-8');
- RAID及热备盘详解
RAID,为Redundant Arrays of Independent Disks的简称,中文为廉价冗余磁盘阵列. 一.出现的原因(RAID的优点): 它的用途主要是面向服务器,但现在的个人电脑由 ...
- 风趣的JavaScript面向对象入门课程一
在我们程序猿界一直流传这这么一个joke,没女票我们可以new一个.没房子没票子没车子我们同样new一个!当然这听着更像是一种自嘲,毕竟我们程序猿都爱自嘲,哈哈,废话不多说,今天就由我带着你们来入Ja ...
- 【bzoj1103】【POI2007】【大都市】(树状数组+差分)
在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之 ...
- Java历程-初学篇 Day04选择结构(1)
一,if 1,单分支 if(条件){ } 示例: 2,双分支 if(条件){ }else{ } 示例: 3,多重if if(条件){ }else if(条件){ }else{ } 示例: 4,嵌套if ...
- Python二维数据分析
一.numpy二维数组 1.声明 import numpy as np #每一个[]代表一行 ridership = np.array([ [ 0, 0, 2, 5, 0], [1478, 3877, ...
- ch7-列表渲染(v-for key 数组更新检测 显示过滤/排序结果)
1 说明 我们用 v-for 指令根据一组数组的选项列表进行渲染. v-for 指令需要以 item in items 形式的特殊语法, items 是源数据数组并且 item 是数组元素迭代的别名. ...
- vue.js用法和特性详解
前 言 最近用Vue.js做了一个数据查询平台,还做了一个拼图游戏,突然深深的感到了vue的强大. Vue.js是一套构建用户界面(user interface)的渐进式框架.与其他重量级框架不 ...