• Hibernate学习笔记(五) — 多对多关系映射


    多对多关系映射

    多对多建立关系相当于在第三张表中插入一行数据

    多对多解除关系相当于在第三张表中删除一行数据

    多对多改动关系相当于在第三张表中先删除后添加

    多对多谁维护效率都一样。看需求

    在实际开发过程中。多对多的映射关系比較常见。

    学生选课演示样例,一个学生能够选多门课,一门课也能够由多个学生去选,这样就形成了多对多的映射关系

    public class Student implements Serializable {
    
    	private static final long serialVersionUID = 1L;
    	private Long sid;
    	private String name;
    	private Set<Course> courses = new HashSet<Course>();
    
    }

    public class Course implements Serializable {
    
    	private static final long serialVersionUID = 1L;
    	private Long cid;
    	private String name;
    	private Set<Student> students = new HashSet<Student>();
    }
    *hbm.xml

    <class name="Student" table="STUDENT">
    		<id name="sid">
    			<generator class="native"></generator>
    		</id>
    		<property name="name"></property>
    		<set name="courses" table="student_courses"  inverse="false" cascade="save-update">
    			<key column="sid"></key>
    			<many-to-many class="Course" column="cid"></many-to-many>
    		</set>
    		<!-- 两个id的书写,要记牢 -->
    	</class>
    <class name="Course" table="COURSE">
    		<id name="cid">
    			<generator class="native"></generator>
    		</id>
    		<property name="name"></property>
    		<!-- table第三张表的名字:不写会会默认生成,可能会出现两张第三张表 -->
    		<set name="students" table="student_courses">
    			<!-- 
    				外键
    			 -->
    			<key column="cid"></key>
    			<!-- 
    				column:外键
    			 -->
    			<many-to-many class="Student" column="sid"></many-to-many>
    		</set>
    	</class>

    測试类:

    public class many2manyTest {
    
    	private Session session;
    	private Transaction transaction;
    	
    	@Before
    	public void init(){
    		session = HibernateUtils.openSession();
    		transaction = session.beginTransaction();
    	}
    	
    	/**
    	 * 学生 级联操作
    	 * 保存的学生的时候,级联保存课程
    	 */
    	@Test
    	public void testSaveStudent_cascade_SaveCourse(){
    		
    		Student student = new Student();
    		student.setName("A");
    		Course course = new Course();
    		course.setName("a");
    		
    		Set<Course> courses = new HashSet<Course>();
    		Set<Student> students = new HashSet<Student>();
    		
    		courses.add(course);
    		student.setCourses(courses);
    		students.add(student);
    		session.save(student);
    		//session.save(course);
    	}
    	
    	/**
    	 * 已经存在一个学生,一个课程,关联两者关系
    	 */
    	@Test
    	public void testBuildRelationship(){
    		
    		Student student = (Student) session.get(Student.class, 2L);
    		Course course = (Course) session.get(Course.class, 2L);
    		//System.out.println(student.getCourses().size()); //0,说明即使学生没有课程,Set<Course> hibernate来帮我们创建,前提是Student类是持久化的
    															//建议类中定义Set<>时,直接new 出 hashSet
    		/**
    		 * student.getCourses().add(course);
    			course.getStudents().add(student); //报错,仅仅能有一个来进行加入操作,
    				//从 学生来建立关系 或 从课程来建立关系  都能够
    		 */
    		student.getCourses().add(course);
    	}
    	
    	/**
    	 * 已经有一个课程,新建一个学生,建立关系
    	 */
    	@Test
    	public void testSaveStudent_BuildR(){
    		Course course = (Course) session.get(Course.class, 2L);
    		Student student = new Student();
    		student.setName("BB");
    		//student.getCourses().add(course);//假设不定义Set<> = new HashSet<>,会空指针异常,3条sql
    	/*	Set<Course> courses = new HashSet<Course>();
    		courses.add(course);
    		student.setCourses(courses);3条sql*/
    		
    //		course.getStudents().add(student);//4条sql
    		
    		student.getCourses().add(course);
    		/**
    		 * hibernate程序,效率与写法有非常大关系
    		 */
    		session.save(student);
    	}
    	
    	/**
    	 * 一个学生从一门课程,转学 还有一门课程
    	 * sid为5的学生从课程2转到课程1
    	 */
    	@Test
    	public void testTransform(){
    		Student student = (Student) session.get(Student.class,5L);
    		Course course = (Course) session.get(Course.class, 1L);
    		Course course2 = (Course) session.get(Course.class, 2L);
    		student.getCourses().remove(course2);//解除学生和cid为2的课程
    		student.getCourses().add(course);//6条sql,jdbc仅仅需update,这就是hibernate的坑爹之处
    	}
    	
    	/**
    	 * 解除一个学生和该学生所学的全部的课程之间的关系
    	 */
    	@Test
    	public void testRealseAllR(){
    		/**
    		 * 解除sid为1的学生和全部的课程之间的关系
    		 */
    		Student student = (Student)session.get(Student.class, 1L);
    		student.setCourses(null);
    		transaction.commit();
    		session.close();
    	}
    	
    	/**
    	 * 解除一个学生和全部的课程之间的关系。再建立一些课程之间的关系
    	 */
    	@Test
    	public void testRealseAllRAndBuildR(){
    		Student student = (Student)session.get(Student.class, 1L);
    		
    		/**
    		 * 由于 再建立一些课程之间的关系,所以用Set,千万不要一个一个add
    		 */
    		Set<Course> courses = new HashSet<Course>();
    		Course course = (Course)session.get(Course.class, 3L);
    		courses.add(course);
    		//把原来的student中的courses给覆盖掉了
    		student.setCourses(courses);
    	}
    	
    	@After
    	public void destory(){
    		transaction.commit();
    		session.close();
    	}
    }
    

    而一对一关系映射。一般不写one-to-one,是把one-to-many,many的一方加入unique="true"

  • 相关阅读:
    Python编程题44反转链表
    Python编程题45移除链表元素
    docker Redis 安裝路徑
    2: 写一个demo(zeppeline 上用flink SQL 读kafka数据)
    1: docker 安装 zeppeline
    3: 读取kafka数据写如mysql
    Linux 远程挂载 Ceph RBD 磁盘
    【Linux网络编程】字节序
    【Linux命令】iptables 禁止 IP和端口
    Jenkins发布服务报错Fatal error: put encountered an exception while uploading磁盘空间不足处理 No space left on device
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7206669.html
Copyright © 2020-2023  润新知