Hibernate学习笔记七(JPA多表映射)

  • 注:这是笔者在学习过程的小小知识记录,可能有错误的地方,仅供参考

JPA的表映射关系

在JPA同样也有一对多,多对多等的多表关系,因为没有了映射文件,因此持久化类与持久化类之间的关系也是由注解来进行定义。

一对多关系

  • 持久化类的代码示例
  1. Company类(一的一方)
package com.wzm.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.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/*
 * Entity表明这是一个持久化类
 * Table表明这个类所对应的表,name为数据库的表名
 */
@Entity
@Table(name="company")
public class Company {
	/*
	 * Id表明这是持久化类的OID
	 * Column表明该属性所对应的表字段,name为表字段名
	 * @GeneratedValue:定义OID的自增长方式
	 */
	@Id
	@Column(name="cid")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long cid;
	@Column(name="cname")
	private String cname;
	
	/*
	 * 	公司可以有很多员工,因此公司属于一的一方,在一的一方要有多的一方的对象集合Set<Employee> employees
	 * @OneToMany表明这是一个一对多的关系,并且这是一的一方
	 * targetEntity为对方的Class对象
	 * mappedBy表明自己这方被对方的哪个属性所映射,注意该属性不能与注解joinColumn和joinTable共存,否则会报错
	 * 	在多的一方会有一的一方的对象,这里就填对方所定义的对象的属性名
	 *	 注意,这个属性只在onetomany中有,也就是只在一的一方有
	 *	mappedBy属性一般都要加上,否则本方不会认同对方创建的外键,会自己再创建出一个中间表
	 *	属性:cascade定义级联操作,PERSIST保存,MERGE级联更新,REMOVE级联删除,ALL级联所以操作
	 *		fetch:定义加载方式,EAGER立即加载,LAZY延迟加载
	 */
	@OneToMany(targetEntity=Employee.class,mappedBy="company",cascade=CascadeType.PERSIST,fetch=FetchType.LAZY)
	private Set<Employee> employees = new HashSet<>();
//省略getter和setter
}

  1. Employee类(多的一方)
package com.wzm.entity;

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为数据库的表名
 */
@Entity
@Table(name="employee")
public class Employee {
	/*
	 * Id表明这是持久化类的OID
	 * Column表明该属性所对应的表字段,name为表字段名
	 * @GeneratedValue:定义OID的自增长方式
	 */
	@Id
	@Column(name="eid")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long eid;
	@Column(name="ename")
	private String ename;
	/*
	 *	 很多员工都属于同一家公司,员工属于多的一方,在多的一方要有一的一方的对象Company company,这个属性名在一的一方的mappeBy会用到
	 *	@ManyToOne表明这是一对多关系,同时这属于多的一方
	 *	targetEntity为对方的class对象
	 *	在多的一方所对应的数据库的表中,一般都有一个外键指向一的一方
	 *	@JoinColumn这表明往表中添加一个外键,name为外键的字段名,注意该注解不能与属性mappedBy共存,否则会报错
	 *	因为外键一般指向一个对应的主键,referencedColumnName就是填所对应的主键,
	 *	这里外键指向一的一方的主键,填的就是一的一方所对应表的主键字段名
	 */
	@ManyToOne(targetEntity=Company.class)
	@JoinColumn(name="cid",referencedColumnName="cid")
	private Company company;
//省略getter和setter
}

  • 一对多关系的基本操作
@Test
	public void test3() {
		//创建一个实体管理工厂,EntityManagerFactory类似于SessionFactory,
		//传入的参数要与persistence.xml中的persistence-unit的name属性一致
		//类似于加载配置文件
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("mysql");
		//获取实体管理对象,类似hibernate的session对象
		EntityManager em = emf.createEntityManager();
		//获取事务对象,在JPA中同样也要启用事务
		EntityTransaction transaction = em.getTransaction();
		//开启事务
		transaction.begin();
		//创建一个公司对象和两个员工对象
		Company company = new Company();
		company.setCname("byte");
		Employee e1 = new Employee();
		e1.setEname("xiaoming");
		Employee e2 = new Employee();
		e2.setEname("daming");
		//关联对象之间的关系
		company.getEmployees().add(e1);
		company.getEmployees().add(e2);
		e1.setCompany(company);
		e2.setCompany(company);
		//保存对象,这里如果只单独保存公司对象不会像hibernate会报错,因为在hibernate双方默认会维护外键,
		//在JPA中,正常配置的话,一的一方默认是不会维护外键的
		//其他的基本操作都与hibernate类似
		em.persist(company);
		em.persist(e1);
		em.persist(e2);
		//提交事务
		transaction.commit();
		//关闭资源
		em.close();
		emf.close();
	}
  • 一对多关系的级联操作
@Test
	public void test4() {
		//创建一个实体管理工厂,EntityManagerFactory类似于SessionFactory,
		//传入的参数要与persistence.xml中的persistence-unit的name属性一致
		//类似于加载配置文件
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("mysql");
		//获取实体管理对象,类似hibernate的session对象
		EntityManager em = emf.createEntityManager();
		//获取事务对象,在JPA中同样也要启用事务
		EntityTransaction transaction = em.getTransaction();
		//开启事务
		transaction.begin();
		//创建一个公司对象和两个员工对象
		Company company = new Company();
		company.setCname("byte");
		Employee e1 = new Employee();
		e1.setEname("xiaoming");
		Employee e2 = new Employee();
		e2.setEname("daming");
		//关联对象之间的关系
		company.getEmployees().add(e1);
		company.getEmployees().add(e2);
		e1.setCompany(company);
		e2.setCompany(company);
		//因为每次保存公司还保存员工太繁琐,因此可以使用级联在保存公司时自动保存关联的员工
		//在一的一方的@OneToMany添加属性cascade=CascadeType.PERSIST,就可以级联保存
		//JPA也可以双向级联操作
		//级联操作都与hibernate类似,注意避免使用级联删除
		em.persist(company);
		//提交事务
		transaction.commit();
		//关闭资源
		em.close();
		emf.close();
	}

多对多关系

  • 持久化类的代码示例
  1. Student类(放弃外键维护的一方)
package com.wzm.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.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

/*
 * Entity表明这是一个持久化类
 * Table表明这个类所对应的表,name为数据库的表名
 */
@Entity
@Table(name="student")
public class Student {
	/*
	 * Id表明这是持久化类的OID
	 * Column表明该属性所对应的表字段,name为表字段名
	 * @GeneratedValue:定义OID的自增长方式
	 */
	@Id
	@Column(name="sid")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long sid;
	@Column(name="sname")
	private String sname;
	
	/*
	 * 在多对多的关系中,双方都要有对方的对象集合
	 * @ManyToMany表明这是多对多的关系,targetEntity为对方的class对象,mappedBy为对方所定义的本方对象集合的属性名
	 * 注意:mappedBy不能与注解@JoinColumn和@JoinTabe共存
	 * 	使用mappedBy相当于放弃外键的维护,直接由对方支配,
	 * 在多对多关系中双方不能同时有JoinTable注解,否则会报错,
	 * 同时没有jointable注解的一方要有mappedBy属性,否则本方不会认同对方创建的中间表,会自己再创建的中间表
	 * 
	 *	 属性:cascade定义级联操作,PERSIST保存,MERGE级联更新,REMOVE级联删除,ALL级联所以操作
	 *		fetch:定义加载方式,EAGER立即加载,LAZY延迟加载
	 */
	@ManyToMany(targetEntity=Teacher.class,mappedBy="students",cascade=CascadeType.PERSIST,fetch=FetchType.LAZY)
	private Set<Teacher> teachers = new HashSet<>();
//省略getter和setter
}
  1. Teacher类(维护外键的一方)
package com.wzm.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.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="teacher")
public class Teacher {
	/*
	 * Id表明这是持久化类的OID
	 * Column表明该属性所对应的表字段,name为表字段名
	 * @GeneratedValue:定义OID的自增长方式
	 */
	@Id
	@Column(name="tid")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long tid;
	@Column(name="tname")
	private String tname;
	
	/*
	 * 在多对多的关系中,双方都要有对方的对象集合
	 * @ManyToMany表明这是多对多的关系,targetEntity为对方的class对象
	 * 因为在多对多的关系中,一般都需要一个中间表,
	 * @JoinTable就是往数据库中加入中间表,属性name为中间表的表名,注意该注解不能与属性mappedBy共存,否则会报错
	 * 在中间表中一般有两个外键分别指向两张表,
	 * 属性joinColumns就是就是往中间表加入一个外键指向本方,
	 * 在属性中又定义一个注解@JoinColumn,注解中属性name为中间表指向本方的外键字段名,referencedColumnName就是本方对应表的主键字段名
	 * 属性inverseJoinColumns就是往中间表加入外键指向对方
	 * 在属性中又定义一个注解@JoinColumn,注解中属性name为中间表指向对方的外键字段名,referencedColumnName就是对方对应表的主键字段名
	 * JoinTable在哪一方都可以,只是没有该注解的另一方就要有mappedBy属性
	 * 
	 * 	属性:cascade定义级联操作,PERSIST保存,MERGE级联更新,REMOVE级联删除,ALL级联所以操作
	 *		fetch:定义加载方式,EAGER立即加载,LAZY延迟加载
	 */
	@ManyToMany(targetEntity=Student.class,cascade=CascadeType.PERSIST,fetch=FetchType.LAZY)
	@JoinTable(name="stu_tea_tab",
	joinColumns= {
			@JoinColumn(name="tid",referencedColumnName="tid")
	},inverseJoinColumns= {
			@JoinColumn(name="sid",referencedColumnName="sid")
	})
	private Set<Student> students = new HashSet<>();
//省略getter和setter
}
  • 多对多关系的基本操作
@Test
	public void test5() {
		//创建一个实体管理工厂,EntityManagerFactory类似于SessionFactory,
		//传入的参数要与persistence.xml中的persistence-unit的name属性一致
		//类似于加载配置文件
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("mysql");
		//获取实体管理对象,类似hibernate的session对象
		EntityManager em = emf.createEntityManager();
		//获取事务对象,在JPA中同样也要启用事务
		EntityTransaction transaction = em.getTransaction();
		//开启事务
		transaction.begin();
		//创建两个学生对象和两个老师对象
		Teacher t1 = new Teacher();
		t1.setTname("t1");
		Teacher t2 = new Teacher();
		t2.setTname("t2");
		Student s1 = new Student();
		s1.setSname("s1");
		Student s2 = new Student();
		s2.setSname("s2");
		//关联对象之间的关系
		t1.getStudents().add(s1);
		t1.getStudents().add(s2);
		t2.getStudents().add(s2);
		s1.getTeachers().add(t1);
		s2.getTeachers().add(t1);
		s2.getTeachers().add(t2);
		//保存对象,其他的基本操作都与hibernate类似
		em.persist(t1);
		em.persist(t2);
		em.persist(s1);
		em.persist(s2);
		//提交事务
		transaction.commit();
		//关闭资源
		em.close();
		emf.close();
	}
  • 多对多关系的级联操作
@Test
	public void test6() {
		//创建一个实体管理工厂,EntityManagerFactory类似于SessionFactory,
		//传入的参数要与persistence.xml中的persistence-unit的name属性一致
		//类似于加载配置文件
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("mysql");
		//获取实体管理对象,类似hibernate的session对象
		EntityManager em = emf.createEntityManager();
		//获取事务对象,在JPA中同样也要启用事务
		EntityTransaction transaction = em.getTransaction();
		//开启事务
		transaction.begin();
		//创建两个学生对象和两个老师对象
		Teacher t1 = new Teacher();
		t1.setTname("t1");
		Teacher t2 = new Teacher();
		t2.setTname("t2");
		Student s1 = new Student();
		s1.setSname("s1");
		Student s2 = new Student();
		s2.setSname("s2");
		//关联对象之间的关系
		t1.getStudents().add(s1);
		t1.getStudents().add(s2);
		t2.getStudents().add(s2);
		s1.getTeachers().add(t1);
		s2.getTeachers().add(t1);
		s2.getTeachers().add(t2);
		//同样JPA的多对多也支持级联操作,@ManyToMany添加属性cascade=CascadeType.PERSIST,就可以级联保存
		//JPA也可以双向级联操作
		//多对多一般不使用级联操作,还要避免使用级联删除
		//级联保存,其他操作和hibernate类似
		em.persist(t1);
		em.persist(t2);
		//提交事务
		transaction.commit();
		//关闭资源
		em.close();
		emf.close();
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值