关联映射
多张表之间有哪些关系?多个实体类
1.一对一关系 市民—社保卡 一个公民—身份证
2.一对多关系 班级—学生
3.多对多关系 老师—学生
表
与表之间关联之一对一关联:
思路:
1. 这两个关联的实体,谁来维护二者之间的关系。一对一关系,随便选择一端维护。选择wife维护关系。
2. 考虑关联,关联就是你中有我,我中有你
Husband代码:
package com.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="husband",schema="chidianwei")
public class Husband {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
@OneToOne(mappedBy="husband")
private Wife wife;
public Wife getWife() {
return wife;
}
public void setWife(Wife wife) {
this.wife = wife;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Wife代码:
package com.entity;
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="wife",schema="chidianwei")
public class Wife {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
@ManyToOne
@JoinColumn(name="husband_id",unique=true)
private Husband husband;
public int getId() {
return id;
}
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
一般情况下谁持有外键,就让谁维护。
/* @Test
public void testOne2One() {
Husband h=new Husband();
h.setName("husband");
Wife w=new Wife();
w.setName("wife");
w.setHusband(h);//wife维护二者一对一关系
session.save(h);
session.save(w);
Husband h=(Husband)session.get(Husband.class, 61);
System.out.println(h.getWife().getName());
}*/
表与表之间关联之一对多关联
单项一对多
相对于学生来说是多对一,相对于班级来说是一对多。
一般总结出来的最佳实践是:有外键的一端也就是多的一端来维护二者的关系,也就是,没有外键的那一端一般情况是一的一端,只要写一个mappedBy注解即可。具体有对方维护关系。
双向一对多关联
维护关系的一端,也叫被控端student映射类代码:
package com.entity;
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="student",schema="chidianwei")
public class Student{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private String name;
private int age;
@ManyToOne
@JoinColumn(name="class_id")
private Classes classes;
public Classes getClasses() {
return classes;
}
public void setClasses(Classes classes) {
this.classes = classes;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
主控端代码:
package com.entity;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="classes",schema="chidianwei")
public class Classes{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@OneToMany(mappedBy="classes")
private List<Student> students=new ArrayList<Student>();
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
持久化代码片段
@Test
public void testOne2Many() {
/* Classes c=new Classes();
c.setName("Java班");
Student s1=new Student();
s1.setName("张三");
s1.setAge(22);
s1.setClasses(c);
Student s2=new Student();
s2.setName("李四");
s2.setAge(25);
s2.setClasses(c);
// 保存
session.save(c);
session.save(s1);
session.save(s2);*/
Classes c=(Classes)session.get(Classes.class, 63);
System.out.println("班级:"+c.getName());
List<Student> students=c.getStudents();
for(Student s:students){
System.out.println(s.getName());
}
}
一对多关系默认加载班级的时候会采用懒加载去设置students属性,也就是学生集合会在真正使用的时候加载。
可以对懒加载进行修改:
@OneToMany(mappedBy=”classes”,fetch=FetchType.EAGER)
这样就不会采用懒加载。
表与表之间关联之多对多
中间的关联表除了两端的外键,还有其他字段,形成了两个一对多关系,对于两端来说,就是多对多关系,就是前边涉及的一对多双向关联,只不过是两对
中间的关联表只有两端的外键,无需对应实体类
主控端:大学生实体类
package com.entity;
import java.util.ArrayList;
import java.util.List;
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;
import javax.persistence.Table;
@Entity
@Table(name="undergraduate",schema="chidianwei")
public class Undergraduate {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany
@JoinTable(
schema="chidianwei",
name="undergraduate_course", //关联表的表名
//关联当前表的外键名
joinColumns=@JoinColumn(name="undergraduate_id"),
//关联对方表的外键名
inverseJoinColumns=@JoinColumn(name="course_id")
)
private List<Course> courses=new ArrayList<Course>();
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
另一端课程实体类:
package com.entity;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name="courses",schema="chidianwei")
public class Course {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany(mappedBy="courses")
private List<Undergraduate> students=new ArrayList<Undergraduate>();
public List<Undergraduate> getStudents() {
return students;
}
public void setStudents(List<Undergraduate> students) {
this.students = students;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
由于是多对多关系,所以谁来当维护关系一端区别不大,缓过来让Course来当维护关系一端也未尝不可。
持久化代码:
/*@Test
public void testMany2Many() {
Course c1=new Course();
c1.setName("语文");
Course c2=new Course();
c2.setName("大学英语");
//学生
Undergraduate s1=new Undergraduate();
s1.setName("张三");
Undergraduate s2=new Undergraduate();
s2.setName("李四");
Undergraduate s3=new Undergraduate();
s3.setName("王五");
//学生选课
List<Course> courses=new ArrayList<Course>();
List<Course> courses1=new ArrayList<Course>();
courses.add(c2);
courses.add(c1);
courses1.add(c1);
s1.setCourses(courses);
s2.setCourses(courses);
s3.setCourses(courses1);
//保存
session.save(c1);
session.save(c2);
session.save(s1);
session.save(s2);
session.save(s3);
}
*/
解释小问题
1.懒加载
lazy属性,延迟加载,即是否立刻查询并加载当前对象关联的对象
XxxToYyy的关系中都有,配置方式类似:
@OneToMany(fetch=FetchType.LAZY)
@OneToMany(fetch=FetchType.EAGER)
凡是@xxxToOne,默认都是EAGER
凡是@xxxToMany,默认都是LAZY
session关闭后再去加载关联对象,会报抛出LazyInitializationException
写法是: @OneToMany(mappedBy=”classes”,fetch=FetchType.EAGER)
2.级联
cascade属性,级联操作,指的是操作当前实体对象时,关联对象是否执行同步操作,例如:Classes对象删除时,相关联的Student是否同时全部删除
例如:@OneToMany(cascade={CascadeType.PERSIST,CascadeType.REMOVE}))
CascadeType枚举值:
PERSIST:在执行persist方法时进行级联操作
MERGE:在执行merge方法时进行级联操作(类似saveOrUpdate方法)
REMOVE:在执行delete方法时进行级联操作
REFRESH:在执行refresh方法时进行级联操作
DETACH:在执行detach方法时进行级联操作
ALL:在执行以上所有操作时都进行级联操作
不设置:所有情况下均不进行级联
SAVE
UPDATE
DELETE 红色的是hibernate的。
这里特别注意,如果准备用JPA注解做级联,必须调用响应的session方法,比如级联值为persist则必须session.persist才生效,save就会不产生级联,如果非要使用session.save或者session.saveOrUpdate,则应该采用Hibernate的级联。@Cascade(value = org.hibernate.annotations.CascadeType.SAVE_UPDATE)
增删改查放在下一篇吧,太多了大家不爱看