Hibernate中多对多

1. 多对多pojo及映射信息

          1)表结构分析
              多对多需要有一张中间表,只有两列且均引用外键,分别就是两张主体表的主键
          2)pojo
public class Student {
        private Long id;
        private String name;
        private Set<Teacher> teachers = new HashSet<Teacher>();<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">}</span>
public class Teacher {
        private Long id;
        private String name;
        private Set<Student> students = new HashSet<Student>();
	..........
}
          3)  映射文件
 <class name="cn.com.cpf.pojo.Student"   table="t_student" >
     <id name="id" column="id">
  	<generator class="native"/>
     </id>
     <property name="name"/>
     <set name="teachers" table="teacher_student">
        <key column="studentId"/>
        <many-to-many class="cn.com.cpf.pojo.Teacher" column="teacherId"/>
     </set>
 </class>
 <class name="cn.com.cpf.pojo.Teacher"   table="t_teacher" >
     <id name="id" column="id">
  	<generator class="native"/>
     </id>
     <property name="name"/>
     <set name="students" table="teacher_student">
        <key column="teacherId"/>
        <many-to-many class="cn.com.cpf.pojo.Student" column="studentId"/>
     </set>
 </class>

       理解:其实也就是Set映射,key为外键,为关联到本类的主键列;因为Set中是类,所以使用class
        4)结果
           t_student表       
           
          t_teacher表
           
          teacher_student表
         
        

2. save操作

      1)多对多双方都未配置inverse=true,且代码中双方均保存了对方对象

               service中代码:
        SessionFactory factory = null;
        Session session = null;
        try 
        {
           factory = new Configuration().configure().buildSessionFactory();
           session = factory.openSession();
           Transaction tx = session.beginTransaction();
		
           Student student1 = new Student();
           student1.setName("xny");
		
           Student student2 = new Student();
           student2.setName("zq");
	
           Teacher teacher1 = new Teacher();
           teacher1.setName("ma");

           Teacher teacher2 = new Teacher();
           teacher2.setName("shi");

           student1.getTeachers().add(teacher1);
           student1.getTeachers().add(teacher2);
           student2.getTeachers().add(teacher1);
           student2.getTeachers().add(teacher2);

           teacher1.getStudents().add(student1);
           teacher1.getStudents().add(student2);
           teacher2.getStudents().add(student1);
           teacher2.getStudents().add(student2);

           session.save(student1);
           session.save(student2);
           session.save(teacher1);
           session.save(teacher2);

	   tx.commit();
	}
              映射信息:
  <set name="teachers" table="teacher_student">
        <key column="studentId"/>
        <many-to-many class="cn.com.cpf.pojo.Teacher" column="teacherId"/>
  </set>
  <set name="students" table="teacher_student">
        <key column="teacherId"/>
        <many-to-many class="cn.com.cpf.pojo.Student" column="studentId"/>
  </set>
              结果:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1-1' for key 'PRIMARY'
            原因:在多对多关系中,中间表使用的是联合主键,而在映射文件中双方都维护多对多关系(也就是在插入的时候都将值插入中间表),这样就相当于同一个值在中间表中插入两次,所以就会报主键重复错误——解决方法为只有一端维护关系

     2)多对多双方只有一方维护关系
          映射文件:
  <set name="students" table="teacher_student" inverse="true">
        <key column="teacherId"/>
        <many-to-many class="cn.com.cpf.pojo.Student" column="studentId"/>
  </set>

        结果:
Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_teacher (name) values (?)
Hibernate: insert into t_teacher (name) values (?)
Hibernate: insert into teacher_student (studentId, teacherId) values (?, ?)
Hibernate: insert into teacher_student (studentId, teacherId) values (?, ?)
Hibernate: insert into teacher_student (studentId, teacherId) values (?, ?)
Hibernate: insert into teacher_student (studentId, teacherId) values (?, ?)
        t_student:
       
       t_teacher
       
       teacher_student
       
     3)多对多双方都是用了inverse属性
          这样已经不能称之为多对多,因为这个关系双方均不维护,所以根本就不会创建中间表

3. get操作

       Teacher teacher = (Teacher) session.get(Teacher.class, 1l);
       System.out.println(teacher.getName());
       System.out.println(teacher.getStudents());
      
       Student student = (Student) session.get(Student.class, 1l);
       System.out.println(student.getName());
       System.out.println(student.getTeachers());
         结果为:
Hibernate: select teacher0_.id as id1_4_0_, teacher0_.name as name2_4_0_ from t_teacher teacher0_ where teacher0_.id=?
ma
Hibernate: select students0_.teacherId as teacherI2_4_0_, students0_.studentId as studentI1_7_0_, student1_.id as id1_3_1_, student1_.name as name2_3_1_ from teacher_student students0_ inner join t_student student1_ on students0_.studentId=student1_.id where students0_.teacherId=?
[cn.com.cpf.pojo.Student@75f2edd2, cn.com.cpf.pojo.Student@1fdbb27d]
xny
Hibernate: select teachers0_.studentId as studentI1_3_0_, teachers0_.teacherId as teacherI2_7_0_, teacher1_.id as id1_4_1_, teacher1_.name as name2_4_1_ from teacher_student teachers0_ inner join t_teacher teacher1_ on teachers0_.teacherId=teacher1_.id where teachers0_.studentId=?
[cn.com.cpf.pojo.Teacher@2a509df8, cn.com.cpf.pojo.Teacher@391da0]

4. 解除关系

      1)由inverse=true的一端来解除
  <set name="students" table="teacher_student" inverse="true">
        <key column="teacherId"/>
        <many-to-many class="cn.com.cpf.pojo.Student" column="studentId"/>
  </set>
     Teacher teacher = (Teacher) session.get(Teacher.class, 1l);
     teacher.getStudents().clear();
       结果为:
Hibernate: select teacher0_.id as id1_4_0_, teacher0_.name as name2_4_0_ from t_teacher teacher0_ where teacher0_.id=?
      因为没有执行delete语句(所谓解除关系,就是删除中间表中的相关数据),所以显然没有解除
      原因:因为Teacher端的inverse属性为true,不再执行中间表的相关操作了,所以肯定不能用这一端来解除
     2)由inverse=false的一端来解除
  <set name="teachers" table="teacher_student">
        <key column="studentId"/>
        <many-to-many class="cn.com.cpf.pojo.Teacher" column="teacherId"/>
  </set>
     Student student = (Student) session.get(Student.class, 1l);
     student.getTeachers().clear();
         结果:
Hibernate: select student0_.id as id1_3_0_, student0_.name as name2_3_0_ from t_student student0_ where student0_.id=?
Hibernate: select teachers0_.studentId as studentI1_3_0_, teachers0_.teacherId as teacherI2_7_0_, teacher1_.id as id1_4_1_, teacher1_.name as name2_4_1_ from teacher_student teachers0_ inner join t_teacher teacher1_ on teachers0_.teacherId=teacher1_.id where teachers0_.studentId=?
Hibernate: delete from teacher_student where studentId=?

5. 删除

        1) 无关联对象:直接删除即可
        2) 有关联对象,且inverse=true
Teacher teacher = (Teacher) session.get(Teacher.class, 1l);
session.delete(teacher);
       结果:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`teacher_student`, CONSTRAINT `FK_ssifa0mqor3f0e70gmvue7lc6` FOREIGN KEY (`teacherId`) REFERENCES `t_teacher` (`id`))
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
       愿意:因为根本不能操作中间表,所以肯定会报外键异常
        3) 有关联对象,且inverse=false
        Student student = (Student) session.get(Student.class, 2l);
        session.delete(student);
Hibernate: select student0_.id as id1_3_0_, student0_.name as name2_3_0_ from t_student student0_ where student0_.id=?
Hibernate: delete from teacher_student where studentId=?
Hibernate: delete from t_student where id=?


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值