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 ...
随机推荐
- 爬虫实战:爬虫之 web 自动化终极杀手 ( 上)
欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:陈象 导语: 最近写了好几个简单的爬虫,踩了好几个深坑,在这里总结一下,给大家在编写爬虫时候能给点思路.本次爬虫内容有:静态页面的爬 ...
- 如何用一天时间实现自己的RPC框架
前言 最近,闲来无事,自己写了一个简单的RPC框架,我把它叫做SimpleRpc.它有多简单?一共只有1400行代码.这个RPC只是作为自己试验作品,交流技术之用,当然如果你敢用,也可以放到生产环境之 ...
- JVM菜鸟进阶高手之路三
转载请注明原创出处,谢谢! 笨神大大分享: 小程序里面搜索:JVMPocket,这个小程序是笨神大大提供的,里面可以搜索相关JVM参数,用法. -XX:MaxTenuringThreshold,这个参 ...
- 动易CMS - 设为首页代码和加入收藏代码(兼容各种浏览器)
注意: 这里虽然说是兼容,但是有些浏览器的设置就是不支持用js来把页面设为首页,加入收藏夹,只能让用户手动去在浏览器或者按键去设置这些功能,这里说的兼容是指当浏览器有这个设置的时候js会有提示. ...
- 安装myeclipse2015 stable 3.0破解之后发生出现SECURITY ALERT:iNTEGRITY CHECK ERROR然后闪退解决方案
安装好myeclipse2015 stable以后也一步步按着破解文件的步骤来进行.打开myEclipse---->Subscription information--->Subscrip ...
- 怎样使用自定义标签简化 js、css 引入?
国庆将至,工作兴致全无,来总结点项目里平时不起眼干货. 前端引入 js .css 一般是这样: <script type="text/javascript" src=&quo ...
- Html事件冒泡
原以为span不同于input,事件冒泡会被父级标签吞噬,写了个测试事件冒泡的Demo,发现并不是想得那样.另外:event.stopPropagation()以及event.stopImmediat ...
- FPGA在其他领域的应用(四)
工业领域: 从工厂和过程自动化到能源基础设施和机器视觉系统,工业产品有助于改善我们的世界.产品必须安全.可靠.适应性强,而且耐用.同时,商业成功要求你在激烈竞争的市场中行动迅速,同时降低总成本. 英特 ...
- ZOJ1171
错误代码先放这 #include<cstdio> #include<cstdlib> #include<iostream> #include<cstring& ...
- IDL 存储数组
IDL中的数组在内存中是按行存储的,这是因为IDL最初设计的设计目的是用来处理行扫描卫星数据. 1.一维数组 m个元素的一维数组arr[m]的存储方式为 arr[0]→arr[1]→...→arr[m ...