打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
hibernate级联关系

JPA双向一对多和多对一

  JPA中一对多和多对一双向关系中,多的一方为关系维护端 。有mappedBy的一方为关系被维护端。

  关系维护端负责外键纪录的更新 ,关系被维护端是没有权力更新外键纪录的。只能通过关系维护端设置与关系被维护端的关系。

一对多:

@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
            CascadeType.MERGE, CascadeType.REMOVE, CascadeType.ALL }, fetch = FetchType.EAGER, mappedBy = "order")

cascade:设置级联操作,对JPQL语句进行的操作没有任何影响

CascadeType.PERSIST对应实体管理器的persist()方法

CascadeType.REFRESH对应实体管理器的refresh()方法

CascadeType.MERGE对应实体管理器的merge()方法

CascadeType.REMOVE对应实体管理器的remove()方法

CascadeType.ALL对应实体管理器的以上方法:persist()、refresh()、merge()、remove()方法

fetch:设置是否延迟加载,FetchType.LZAY为延迟加载, FetchType.EAGER时立即加载。如果加载的是多的一方的话,默认的是延迟加载,否则是加载。

多对一:

@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
@JoinColumn(name = "order_id")

optional:代表外键字段是否可以为空。true可以为空,false不可以为空。

@JoinColumn(name = "order_id"):设置关联外键字段的名称。

 

例:

1.两个实体的一对多和多对一

使用现实生活中的订单和订单项的关系,代码为:

package com.taoistwar.jpa.entity.onetomany;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "order_info")
public class OrderInfo {
private Integer id;
private String name;
private Set<OrderItem> items = new HashSet<OrderItem>();
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.EAGER, mappedBy = "order")
//fetch是否延迟加载,mappedBy有它的一方为关系被维护端。
public Set<OrderItem> getItems() {
return items;
}
public void setItems(Set<OrderItem> items) {
this.items = items;
}
public void addOrderItem(OrderItem orderItem) {
orderItem.setOrder(this);
this.items.add(orderItem);
}
}
 
package com.taoistwar.jpa.entity.onetomany;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "order_item")
public class OrderItem {
private Integer Id;
private String name;
private OrderInfo order;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return Id;
}
public void setId(Integer id) {
Id = id;
}
@Column(length = 20, nullable = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
@JoinColumn(name = "order_id")
// optional是否可以为空
public OrderInfo getOrder() {
return order;
}
public void setOrder(OrderInfo order) {
this.order = order;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((Id == null) ? 0 : Id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OrderItem other = (OrderItem) obj;
if (Id == null) {
if (other.Id != null)
return false;
} else if (!Id.equals(other.Id))
return false;
return true;
}
}

 2.单个实体的一对多和多对一

使用软件开发中的模块为例子,代码如下:

package com.taoistwar.ejb.sys.entity;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* @author TaoistWar 模块实体类 (一对多)
*  JPA中一对多和多对一双向关系中,多的一方为关系维护端。
*	关系维护端负责外键纪录的更新,关系被维护端是没有权力更新外键纪录的。
*/
@Entity
@Table(name = "s_moudle")
public class Moudle implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
// 模块名(一般中文)
@Column(name = "modName")
private String modName;
// 模块值(英文)
@Column(name = "modValue")
private String modValue;
// 模块排序编码
@Column(name = "orderCode")
private Integer orderCode;
// 模块是否禁用
@Column(name = "forbidden")
private boolean forbidden;
// 模块链接路径
@Column(name = "modUrl")
private String modUrl;
// 父级模块
@ManyToOne(cascade = { CascadeType.REFRESH, CascadeType.REMOVE }, optional=true)
@JoinColumn(name="parent_id")
// optional关联字段是否可以为空
private Moudle parent;
// 子级模块
@OneToMany(cascade = { CascadeType.REFRESH, CascadeType.REMOVE }, fetch=FetchType.LAZY, mappedBy="parent")
private Set<Moudle> children;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getModName() {
return modName;
}
public void setModName(String modName) {
this.modName = modName;
}
public String getModValue() {
return modValue;
}
public void setModValue(String modValue) {
this.modValue = modValue;
}
public Integer getOrderCode() {
return orderCode;
}
public void setOrderCode(Integer orderCode) {
this.orderCode = orderCode;
}
public boolean isForbidden() {
return forbidden;
}
public void setForbidden(boolean forbidden) {
this.forbidden = forbidden;
}
public String getModUrl() {
return modUrl;
}
public void setModUrl(String modUrl) {
this.modUrl = modUrl;
}
public Moudle getParent() {
return parent;
}
public void setParent(Moudle parent) {
this.parent = parent;
}
public Set<Moudle> getChildren() {
return children;
}
public void setChildren(Set<Moudle> children) {
this.children = children;
}
}

 

 

     1-m:多的一方为关系维护端,关系维护端负责外键纪录的更新,关系被维护端没有权力更新外键纪录.

 

维护端注解

 

@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
CascadeType.MERGE, CascadeType.REMOVE },
 fetch = FetchType.EAGER,
 mappedBy = "order")

被维护端注解

 

@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
@JoinColumn(name = "order_id")

 

 

 

对于一对多和多对一关系的现实中的例子是,网上购物时的订单和订单项。一个订单有多个订单项。多个订单项属于一个订单。

 

订单实体类:

package com.taoistwar.jpa.entity.onetomany;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "order_info")
public class OrderInfo {
private Integer id;
private String name;
private Set<OrderItem> items = new HashSet<OrderItem>();
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.EAGER,
mappedBy = "order")
public Set<OrderItem> getItems() {
return items;
}
public void setItems(Set<OrderItem> items) {
this.items = items;
}
public void addOrderItem(OrderItem orderItem) {
orderItem.setOrder(this);
this.items.add(orderItem);
}
}

 重点在于:

       @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.EAGER,
 mappedBy = "order")
public Set<OrderItem> getItems() {
return items;
}

 订单项实体类:

package com.taoistwar.jpa.entity.onetomany;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "order_item")
public class OrderItem {
private Integer Id;
private String name;
private OrderInfo order;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return Id;
}
public void setId(Integer id) {
Id = id;
}
@Column(length = 20, nullable = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
@JoinColumn(name = "order_id")
public OrderInfo getOrder() {
return order;
}
public void setOrder(OrderInfo order) {
this.order = order;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((Id == null) ? 0 : Id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OrderItem other = (OrderItem) obj;
if (Id == null) {
if (other.Id != null)
return false;
} else if (!Id.equals(other.Id))
return false;
return true;
}
}

 重点在于:

       @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
@JoinColumn(name = "order_id")
public OrderInfo getOrder() {
return order;
}

 测试类:

package com.taoistwar.jpa.entity.onetomany;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.Test;
public class OneToMany {
@Test
public void save() {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("JPAPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
OrderInfo o = new OrderInfo();
o.setName("订单一");
OrderItem oi1 = new OrderItem();
oi1.setName("产品一");
o.addOrderItem(oi1);
OrderItem oi2 = new OrderItem();
oi2.setName("产品一");
o.addOrderItem(oi2);
OrderItem oi3 = new OrderItem();
oi3.setName("产品一");
o.addOrderItem(oi3);
OrderItem oi4 = new OrderItem();
oi4.setName("产品一");
o.addOrderItem(oi4);
em.persist(o);
// UUID.randomUUID().toString();
em.getTransaction().commit();
emf.close();
}
}
 

 

 JPA多对多

维护端注解

@ManyToMany (cascade = CascadeType.REFRESH)

@JoinTable (//关联表

                   name =  "student_teacher" , //关联表名

                   inverseJoinColumns =  @JoinColumn (name =  "teacher_id" ),//被维护端外键

                   joinColumns =  @JoinColumn (name =  "student_id" ))//维护端外键

被维护端注解

@ManyToMany(

                   cascade = CascadeType.REFRESH,

                   mappedBy = "teachers",//通过维护端的属性关联

                   fetch = FetchType.LAZY)

关系维护端删除时,如果中间表存在些纪录的关联信息,则会删除该关联信息;

关系被维护端删除时,如果中间表存在些纪录的关联信息,则会删除失败 .

 

 

以学生和老师的对应关系为例。一个学生可以拥有多个老师,一个老师也可以拥有多个学生。

学生实体类

package com.taoistwar.jpa.entity.manytomany;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
@Entity
public class Student {
private Integer id;
private String name;
private Set<Teacher> teachers = new HashSet<Teacher>();
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(nullable = false, length = 16)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany(cascade = CascadeType.REFRESH)
@JoinTable(name = "student_teacher", inverseJoinColumns = @JoinColumn(name = "teacher_id"), joinColumns = @JoinColumn(name = "student_id"))
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
public void addTeacher(Teacher teacher) {
this.teachers.add(teacher);
}
public void removeTeachers(Teacher teacher) {
this.teachers.remove(teacher);
}
}

 重点在于:

@ManyToMany(cascade = CascadeType.REFRESH)
@JoinTable(name = "student_teacher", inverseJoinColumns = @JoinColumn(name = "teacher_id"), joinColumns = @JoinColumn(name = "student_id"))
public Set<Teacher> getTeachers() {
return teachers;
}

 老师实体类

package com.taoistwar.jpa.entity.manytomany;
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.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
@Entity
public class Teacher {
private Integer id;
private String name;
private Set<Student> students = new HashSet<Student>();
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(nullable = false, length = 16)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany(cascade = CascadeType.REFRESH, mappedBy = "teachers", fetch = FetchType.LAZY)
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Teacher other = (Teacher) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}

 重点在于:

@ManyToMany(cascade = CascadeType.REFRESH, mappedBy = "teachers", fetch = FetchType.LAZY)
public Set<Student> getStudents() {
return students;
}

 拥有mappedBy注解的实体类为关系被维护端,另外的实体类为关系维护端的。顾名思意,关系的维护端对关系(在多对多为中间关联表)的CRUD做操作。关系的被维护端没有该操作,不能维护关系。

测试类

package com.taoistwar.jpa.entity.manytomany;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.Test;
public class ManyToMany {
@Test
public void save() {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("JPAPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Student student = new Student();
student.setName("小李");
Teacher teacher = new Teacher();
teacher.setName("大李");
em.persist(student);
em.persist(teacher);
em.getTransaction().commit();
emf.close();
}
@Test
public void bind() {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("JPAPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Student student = em.find(Student.class, 1);
Teacher teacher = em.find(Teacher.class, 1);
student.addTeacher(teacher);
em.persist(student);
em.getTransaction().commit();
emf.close();
}
@Test
public void unbind() {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("JPAPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Student student = em.find(Student.class, 1);
Teacher teacher = em.find(Teacher.class, 1);
student.removeTeachers(teacher);
em.persist(student);
em.getTransaction().commit();
emf.close();
}
@Test
public void removeTeacher() {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("JPAPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 关系被维护端删除时,如果中间表存在些纪录的关联信息,则会删除失败
em.remove(em.getReference(Teacher.class, 1));
em.getTransaction().commit();
emf.close();
}
@Test
public void removeStudent() {
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("JPAPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 关系维护端删除时,如果中间表存在些纪录的关联信息,则会删除该关联信息
em.remove(em.getReference(Student.class, 1));
em.getTransaction().commit();
emf.close();
}
}
 

JPA(HIberante)环境的搭建

1.添加jar包

hibernate & jpa jar(15):
hibernate-distribution-3.3.1.GA/hibernate3.jar
hibernate-distribution-3.3.1.GA/lib/required/antlr-2.7.6.jar
hibernate-distribution-3.3.1.GA/lib/required/dom4j-1.6.1.jar
hibernate-distribution-3.3.1.GA/lib/required/commons-collections-3.1.jar
hibernate-distribution-3.3.1.GA/lib/required/jta-1.1.jar
hibernate-distribution-3.3.1.GA/lib/required/javassist-3.4.GA.jar
hibernate-distribution-3.3.1.GA/lib/required/slf4j-api-1.5.2.jar
hibernate-distribution-3.3.1.GA/lib/bytecode/cglib/hibernate-cglib-repack-2.1_3.jar
hibernate-distribution-3.3.1.GA/lib/optional/ehcache-1.2.jar
hibernate-annotations-3.4.0.GA/hibernate-annotations.jar
hibernate-annotations-3.4.0.GA/lib/hibernate-commons-annotations.jar
hibernate-annotations-3.4.0.GA/lib/test/slf4j-log4j12.jar
hibernate-annotations-3.4.0.GA/lib/test/log4j.jar
hibernate-annotations-3.4.0.GA/lib/ejb3-persistence.jar
hibernate-entitymanager-3.4.0.GA/lib/hibernate-entitymanager.jar

 2.在src创建META-INF文件夹,在其下面创建persistence.xml文件,其内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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_1_0.xsd"
version="1.0">
<persistence-unit name="ssj_unit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<!--
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver" />
<property name="hibernate.connection.username" value="yxuser" />
<property name="hibernate.connection.password" value="yxuser" />
<property name="hibernate.connection.url" value="jdbc:oracle:thin:@192.168.1.96:1521:yxdb" />
-->
<!-- 连接参数 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="root" />
<property name="hibernate.connection.url"
value="jdbc:mysql://localhost:3306/ssj?useUnicode=true&characterEncoding=UTF-8" />
<!-- 数据源设置 -->
<property name="hibernate.max_fetch_depth" value="3" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.jdbc.fetch_size" value="50" />
<property name="hibernate.jdbc.batch_size" value="10" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
</persistence>

 3.创建实体类,其内容如下:

package com.taoistwar.ssj.producty.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class ProductType {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
public ProductType() {
super();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

 4.创建测试类

package test.producty.entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.Test;
import com.taoistwar.ssj.producty.entity.ProductType;
public class ProductTypeTest {
@Test
public void testRun() {
try {
EntityManagerFactory emf =  Persistence
.createEntityManagerFactory("ssj_unit");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ProductType pt = new ProductType();
pt.setName("中文");
em.persist(pt);
em.getTransaction().commit();
em.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
JPA之OneToMany和ManyToOne处理
Hibernate 一对多注解 mappedby 作用
注解的力量 -----Spring 2.5 JPA hibernate 使用方法的点滴整理...
JPA对数据库常用操作方法
报错找不到 ClassNotFoundException: javax.persistence.Entity 出错的原因
spring+hibernate Annotation方式整合
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服