Hibernate多对多关联关系的使用

    技术2022-05-19  29

    多对多关系的使用:

    Student.hbm.xml

    <class name="model.Student" table="student"

           select-before-update="true"><!--把类和数表关联起来-->

           <id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->

               <generator class="uuid.hex" />

           </id>

           <property name="cardId" type="string" /><!--映射号-->

           <property name="name" type="string" /><!--映射学生名-->

           <property name="age" type="int" /><!--映射学生岁数-->

           <set name="courses" table="student_course"

               cascade="none">

               <key column="stu_id" />

               <many-to-many class="model.Course"

                  column="course_id" />

           </set>

        </class>

    Course.hbm.xml

    <class name="model.Course" table="course"

           select-before-update="true"><!--把类和数表关联起来-->

           <id name="id" unsaved-value="null" ><!--id的产生方式是uuid.hex-->

               <generator class="uuid.hex" />

           </id>

          

           <property name="name" type="string" /><!--映射课程名-->

          

           <set name="students" table="student_course"

               cascade="save-update">

               <key column="course_id" />

               <many-to-many class="model.Student"

                  column="stu_id" />

           </set>

        </class>

    多对多关系需要配置的属性比较多,需要记住一个原则:<key column=””>总是和本身类的主键id相对应,而<column=””>总是和关联类的主键id相对应。对于上面的Student.hbm.xml,他有个关联类course<key column=””>对应本身类,而本身类是student,所以应该填写stu_id<column=””>对应关联类,关联类是Course,所以应该填写course_id。通过取得student对象而取得course对象集合的过程:首先取得student对象的主键值id,查找student.hbm.xml,根据“stu_id”找出相对应的“course_id”值,然后再去查找course.hbm.xml,找出course中对应的列名,然后根据“course_id”值在course表中找出相对应的集合。

     

    添加关联关系

    测试类:看某个学生的选课情况,

    Student student = (Student)session.get(Student.class, "5abfe4c705ca8ee00105ca8ee42b0001");

               List list = new ArrayList(student.getCourses());

               for(int i = 0;i<list.size();i++){

                  Course course2 = (Course)list.get(i);

                  System.out.println(course2.getName());

               }

              

    控制台输出:

    l  Hibernate: select student0_.id as id0_0_, student0_.cardId as cardId0_0_, student0_.name as name0_0_, student0_.age as age0_0_ from student student0_ where student0_.id=?

    l  Hibernate: select courses0_.stu_id as stu1_1_, courses0_.course_id as course2_1_, course1_.id as id2_0_, course1_.name as name2_0_ from student_course courses0_ left outer join course course1_ on courses0_.course_id=course1_.id where courses0_.stu_id=?

    l  computer

    l  history

    l  music

    现在该学生还想添加ecnomic课程,对于程序员来说只是为该学生添加了一个到ecnomic 的惯量,具体地说就是在student_course表中新添了一条记录,而studentcourse表都不用变更。

    测试类:

    session = HibernateUtil.currentSession(); //开启连接

               tx = session.beginTransaction(); //开启事务

               stu=(Student) session.createQuery("from Student s where s.name ='tomclus'").uniqueResult();

               course=(Course) session.createQuery("from Course c where c.name='ecnomic'").uniqueResult();

               stu.getCourses().add(course);

               course.getStudents().add(stu);

     

    控制台输出:

    l  Hibernate: select student0_.id as id0_, student0_.cardId as cardId0_, student0_.name as name0_, student0_.age as age0_ from student student0_ where student0_.name='tomclus'

    l  Hibernate: select course0_.id as id2_, course0_.name as name2_ from course course0_ where course0_.name='ecnomic'

    l  Hibernate: select courses0_.stu_id as stu1_1_, courses0_.course_id as course2_1_, course1_.id as id2_0_, course1_.name as name2_0_ from student_course courses0_ left outer join course course1_ on courses0_.course_id=course1_.id where courses0_.stu_id=?

    l  Hibernate: select students0_.course_id as course2_1_, students0_.stu_id as stu1_1_, student1_.id as id0_0_, student1_.cardId as cardId0_0_, student1_.name as name0_0_, student1_.age as age0_0_ from student_course students0_ left outer join student student1_ on students0_.stu_id=student1_.id where students0_.course_id=?

    l  Hibernate: insert into student_course (stu_id, course_id) values (?, ?)

    l  Hibernate: insert into student_course (course_id, stu_id) values (?, ?)

    l  ERROR [main] (JDBCExceptionReporter.java:78) - Duplicate entry '5abfe4c705ca8ee00105ca8ee42b0001-

    第一句:执行hql语句记载student对象

    第二句:执行hql语句加载course对象

    第三句:通过辅助表左外连接取得student关联的所有课程

    第四句:通过辅助表左外连接取得course关联的所有课程

    第五句:由stu.getCourses().add(course);语句引入的插入语句

    第六句:由course.getStudents().add(stu);语句引入的插入语句

    第七句:抛出异常,第二次插入内容和第一次相同

    由此可见,在多对多关系中,如果双方都有控制权(也就是双方都没有设置inverse=true”),则双方都要把关联关系反应到数据库,因此才会有第五和第六条语句,插入的内容相同,导致违反数据库主键约束。

    解决方法:

    (1)在course.getStudents().add(stu); stu.getCourses().add(course)中只选择一条执行

    (2)在某一方设置inverse=”true”,然后再执行语句时使用主控方进行操作(也就是没有inverse=true”的哪一方)


    最新回复(0)