hibernate学习-两表关联-第6天
关联关系,是使用最多的一种关系,非常重要。在内存中反映为实体关系,映射到 DB
中为主外键关系。实体间的关联,即对外键的维护。关联关系的发生,即对外键数据的改
变。外键:外面的主键,即,使用其它表的主键值作为自已的某字段的取值。
一、基本概念
前4个请查看 Hibernate5讲义
5、关联方向
(1)单向关联
指具有关联关系的实体对象间的加载与访问关系是单向的。即,只有一个实体对象可
以加载和访问对方,但对方是看不到另一方的。
(2)双向关联
指具有关联关系的实体对象间的加载与访问关系是双向的。即,任何一方均可加载和
访问另一方。
6、关联数量
实体对象间的关系,从数量上可以划分为:1:1,1:n,n:1,m:n 。
二、关系映射
demo代码路径:https://github.com/MisterChegy/hibernate
(1)1:n-单向关联
model类 (get,set方法略过)
/**
* 一对多单向关联
*/
@Entity
@Table(name = "minister", catalog = "test")
public class Minister implements java.io.Serializable {
// Fields
private Integer mid;
private String mname;
/**
*一对多单向关联
*/
@Entity
@Table(name = "country", catalog = "test")
public class Country implements java.io.Serializable {
@Id
@Column(name = "cid", unique = true, nullable = false)
private Integer cid;
@Column(name = "cname", length = 45)
private String cname;
//关联属性
@OneToMany(targetEntity = Minister.class, cascade=CascadeType.ALL)
//用来指定与所操作实体或实体集合相关联的数据库表中的列字段
@JoinColumn(name="cid")
private Set<Minister> ministers = new HashSet<Minister>(0);
测试
/*
* 去掉cascade = CascadeType.ALL和mappedBy =
* "country",即取消级联保存和多端维护,然后添加@JoinColumn(name="cid")
* 添加@JoinColumn(name="cid")可以避免生成中间表
*
* 一对多单向关联
*/
@Test
public void test01() {
try {
session.beginTransaction();
model2.Minister minister1 = new model2.Minister(1, "aaa");
Set<model2.Minister> ministers = new HashSet<model2.Minister>();
ministers.add(minister1);
model2.Country country = new model2.Country(1, "USA");
country.setMinisters(ministers);
System.out.println("country = " + country);
session.save(country);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
结果
(2)1:n-双向关联
model类
/**
* 一对多双向关联
*/
@Entity
@Table(name = "minister", catalog = "test")
public class Minister implements java.io.Serializable {
@Id
@Column(name = "mid", unique = true, nullable = false)
private Integer mid;
@Column(name = "mname", length = 45)
private String mname;
// 关联属性
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "cid")
private Country country;
/**
*一对多双向关联
*/
@Entity
@Table(name = "country", catalog = "test")
public class Country implements java.io.Serializable {
@Id
@Column(name = "cid", unique = true, nullable = false)
private Integer cid;
@Column(name = "cname", length = 45)
private String cname;
//关联属性
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY , mappedBy = "country")
private Set<Minister> ministers = new HashSet<Minister>(0);
测试
/*
* 在 country 的映射文件中的关联属性映射中增加控制反转设置mappedBy =
* "country",注册要删除@JoinColumn(name="cid") 在 country
* 的映射文件中的关联属性映射中增加设置级联操作,或测试类中进行save(minister)。
*
* 一对多双向关联
*/
@Test
public void test02() {
try {
session.beginTransaction();
model.Minister minister1 = new model.Minister(2, "aaa");
model.Country country = new model.Country(2, "USA");
minister1.setCountry(country);
HashSet<model.Minister> ministers = new HashSet<model.Minister>();
ministers.add(minister1);
country.setMinisters(ministers);
session.save(country);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
结果
(3)自关联
model类
/**
* 自关联
*/
@Entity
@Table(name = "column", catalog = "test")
public class Column implements java.io.Serializable {
@Id
@javax.persistence.Column(name = "id", unique = true, nullable = false)
private Integer id;
// 父栏目
// 多方关联属性,多对1映射
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "cid")
private Column parentColumn;
@javax.persistence.Column(name = "name", length = 45)
private String name;
// 子栏目
// 1方关联属性
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parentColumn")
private Set<Column> childrenColumns = new HashSet<Column>(0);
测试
/*
* 自关联 在多端添加cascade = CascadeType.ALL
*/
@Test
public void test03() {
try {
session.beginTransaction();
Column sportsColumn = new Column(1, "体育栏目");
Column footballColumn = new Column(2, "足球栏目");
footballColumn.setParentColumn(sportsColumn);
Column basketballColumn = new Column(3, "篮球栏目");
basketballColumn.setParentColumn(sportsColumn);
System.out.println("footballColumn = " + footballColumn);
System.out.println("basketballColumn = " + basketballColumn);
session.save(footballColumn);
session.save(basketballColumn);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
结果
(4)n:1-单向关联
model类
/**
*多对一单向关联
*/
@Entity
@Table(name = "minister", catalog = "test")
public class Minister implements java.io.Serializable {
@Id
@Column(name = "mid", unique = true, nullable = false)
private Integer mid;
@Column(name = "mname", length = 45)
private String mname;
// 关联属性
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "cid")
private Country country;
/**
* 多对一单向关联
*/
@Entity
@Table(name = "country", catalog = "test")
public class Country implements java.io.Serializable {
@Id
@Column(name = "cid", unique = true, nullable = false)
private Integer cid;
@Column(name = "cname", length = 45)
private String cname;
测试
/*
* 去掉cascade = CascadeType.ALL和mappedBy =
* "country",即取消级联保存和多端维护,然后添加@JoinColumn(name="cid")
* 添加@JoinColumn(name="cid")可以避免生成中间表
*
* 多对一单向关联
*/
@Test
public void test04() {
try {
session.beginTransaction();
model3.Minister minister1 = new model3.Minister(3, "aaa");
model3.Country country = new model3.Country(3, "USA");
minister1.setCountry(country);
System.out.println("minister1 = " + minister1);
session.save(minister1);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
结果
(5)n:m-单向关联
model类
/**
* 多对多单向关联
*/
@Entity
@Table(name = "course", catalog = "test")
public class Course implements java.io.Serializable {
@Id
@Column(name = "cid", unique = true, nullable = false)
private Integer cid;
@Column(name = "cname", length = 45)
private String cname;
/**
* 多对多单向关联
*/
@Entity
@Table(name = "student", catalog = "test")
public class Student implements java.io.Serializable {
@Id
@Column(name = "sid", unique = true, nullable = false)
private Integer sid;
@Column(name = "sname", length = 45)
private String sname;
@ManyToMany
@JoinTable(name = "student_course",
joinColumns = {@JoinColumn(name = "s_id", referencedColumnName = "sid")},
inverseJoinColumns = {@JoinColumn(name = "c_id", referencedColumnName ="cid")})
private Set<Course> courses;
测试
/*
* n:m-单向关联 ,只维护student,student_course;course不更新(需要提前手动更新)
*/
@Test
public void test06() {
try {
session.beginTransaction();
model3.Course course1 = new model3.Course(1, "struts2");
model3.Course course2 = new model3.Course(2, "Hibernate");
model3.Student student = new model3.Student(1, "bbb");
student.getCourses().add(course1);
student.getCourses().add(course2);
System.out.println("student = "+student);
session.save(course1);
session.save(course2);
session.save(student);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
结果
(5)n:m-双向关联
model类
/**
* 多对多双向关联
*/
@Entity
@Table(name = "course", catalog = "test")
public class Course implements java.io.Serializable {
@Id
@Column(name = "cid", unique = true, nullable = false)
private Integer cid;
@Column(name = "cname", length = 45)
private String cname;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "student_course",
joinColumns = {@JoinColumn(name = "c_id", referencedColumnName = "cid")},
inverseJoinColumns = {@JoinColumn(name = "s_id", referencedColumnName ="sid")})
private Set<Student> students;
/**
* 多对多双向关联
*/
@Entity
@Table(name = "student", catalog = "test")
public class Student implements java.io.Serializable {
@Id
@Column(name = "sid", unique = true, nullable = false)
private Integer sid;
@Column(name = "sname", length = 45)
private String sname;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "student_course",
joinColumns = {@JoinColumn(name = "s_id", referencedColumnName = "sid")},
inverseJoinColumns = {@JoinColumn(name = "c_id", referencedColumnName ="cid")})
private Set<Course> courses;
测试
/*
* n:m-双向关联
*/
@Test
public void test05() {
try {
session.beginTransaction();
Course course1 = new Course(1, "struts2");
Course course2 = new Course(2, "Hibernate");
Student student = new Student(2, "aaa");
student.getCourses().add(course1);
student.getCourses().add(course2);
System.out.println("student = "+student);
session.save(student);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
结果