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();
		}
	}

结果
hibernate学习-两表关联-第6天

(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();
		}
	}

结果
hibernate学习-两表关联-第6天

(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();
		}
	}

结果
hibernate学习-两表关联-第6天

(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();
		}
	}

结果
hibernate学习-两表关联-第6天

(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();
		}
	}

结果
hibernate学习-两表关联-第6天

(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();
		}
	}

结果
hibernate学习-两表关联-第6天