多对多关系映射
多对多建立关系相当于在第三张表中插入一行数据
多对多解除关系相当于在第三张表中删除一行数据
多对多修改关系相当于在第三张表中先删除后增加
多对多谁维护效率都一样。看需求
在实际开发过程中,多对多的映射关系比较常见。
学生选课示例,一个学生可以选多门课,一门课也可以由多个学生去选,这样就形成了多对多的映射关系
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"