一对多关联映射(双向)

简介:
 一对多双向,从实体类上讲究是在“多”的一端持有“一”的实例,并在配置文件中用<many-to-one>标签将其配置上。这里有一点要特别注意,当两边都能够维护关系的时候,推荐让“多”的一端来做,做法上就是在“一”一端映射文件的<set>标签中设置属性inverse="true"。另外,<key>中为“多”一端表设置的外键要和<many-to-one>中设置的外键要一样。
1.实体模型:
 
2.关系模型:
 
3.实体类:
   Student.java
public  class Student { 
   private Integer id; 
   private String name; 
   private Classes classes; 
   //一系列的 setter.getter方法 
  @Override 
   public String toString() { 
     return  "name of student: " + name; 
  } 
}
   Classes.java
public  class Classes { 
   private Integer id; 
   private String name; 
   private Set<Student> students; 
   //一系列的setter.getter方法 
  @Override 
   public String toString() { 
     return  "name of class: " + name; 
  } 
}
 
4.映射文件:
   Student.hbm.xml
   < class  name ="com.sxt.hibernate.one2many.entity.Student"  table ="sxt_hibernate_student" > 
     < id  name ="id"  length ="4" > 
       < generator  class ="native" > </ generator > 
     </ id > 
     < property  name ="name"  length ="10" > </ property > 
    <!--  此处column指定的外键要和对方key中指定的外键一致 --> 
     < many-to-one  name ="classes"  column ="class_id"  cascade ="save-update" > </ many-to-one > 
   </ class >
    Classes.hbm.xml
   < class  name ="com.sxt.hibernate.one2many.entity.Classes"  table ="sxt_hibernate_class" > 
     < id  name ="id"  length ="4" > 
       < generator  class ="native" > </ generator > 
     </ id > 
     < property  name ="name"  length ="10" > </ property > 
    <!--  配置集合属性 --> 
    <!-- inverse="true"含义,把关联关系交由对方一端维护,而在操作本方数据时不再维护关系.    --> 
     < set  name ="students"  cascade ="save-update"  inverse ="true" > 
      <!--  key的含义,指在另一端增加的外键指向本主键. 
        如果设置上属性not-null="true",表示该外键非空,则在由"一"的一端维护关系时, 
        可能导致插入数据异常PropertyValueException. 
        
--> 
       < key  column ="class_id" > </ key > 
      <!-- one-to-many含义,指出set集合中的元素类型,以供加载时使用    --> 
       < one-to-many  class ="com.sxt.hibernate.one2many.entity.Student" /> 
     </ set > 
   </ class >
 
5.hibernate配置文件:
   参见上一篇。
 
6.测试方法:
   public  static  void main(String[] args) { 
    Session session = HibernateUtils.getSession(); 
    Transaction t = session.beginTransaction(); 
     try { 
       /** 
        * 测试插入数据 
        */
 
/*      Classes classes = new Classes();//情况1:从"多"的一端保存(这完全就是个多对一的情况) 
      classes.setName("不一班"); 
        
      Student student1 = new Student(); 
      student1.setName("志朋"); 
      student1.setClasses(classes); 
      //存储成功.sql语句如下: 
      //Hibernate: insert into sxt_hibernate_class (name, id) values (?, ?) 
      //Hibernate: insert into sxt_hibernate_student (name, class_id, id) values (?, ?, ?) 
      //Hibernate: insert into sxt_hibernate_student (name, class_id, id) values (?, ?, ?) 
      //为了不至于出现TransientObjectException,应先保存classes对象或者在<many-to-one>中 
         //加上cascade="save-update,all" 
      session.save(student1); 

      Student student2 = new Student(); 
      student2.setName("有朋"); 
      student2.setClasses(classes); 
      //由于此时classes已经是持久化对象了,所以此处不会再存储一遍classes了 
      session.save(student2); 
*/
 
/*      Student student1=new Student();//情况2:从"一"的一端保存 
      student1.setName("志鹏"); 
        
      Student student2=new Student(); 
      student2.setName("有朋"); 
        
      Set<Student> students=new HashSet<Student>(); 
      students.add(student1); 
      students.add(student2); 
        
      Classes classes=new Classes(); 
      classes.setName("不一班"); 
      classes.setStudents(students); 
      //也能正确保存.sql语句如下: 
      //如果<set>标签中没有inverse="true":(情况2.1) 
      //Hibernate: insert into sxt_hibernate_class (name, id) values (?, ?) 
      //Hibernate: insert into sxt_hibernate_student (name, class_id, id) values (?, ?, ?) 
      //Hibernate: insert into sxt_hibernate_student (name, class_id, id) values (?, ?, ?) 
      //Hibernate: update sxt_hibernate_student set class_id=? where id=? 
      //Hibernate: update sxt_hibernate_student set class_id=? where id=? 
      //存储过程是这样的:存classes时,由于有cascade="save-update",它会先触发存储student, 
      //由于默认inverse=false,student不负责维护关系,所以此时它的class_id为空;然后回来存储classes,而此时 
      //classes不得不来维护关系(发出update语句修改student的外键). 
         
      //如果<set>标签中有inverse="true":(情况2.2) 
      //Hibernate: insert into sxt_hibernate_class (name, id) values (?, ?) 
      //Hibernate: insert into sxt_hibernate_student (name, class_id, id) values (?, ?, ?) 
      //Hibernate: insert into sxt_hibernate_student (name, class_id, id) values (?, ?, ?) 
      //但是插入的student记录class_id字段为空,因为"一"一端不再负责维护关系了. 
      //存储过程是这样的:存classes时,由于有cascade="save-update",它会先触发存储student;    
      // 而在存储student时,虽然inverse="true"指明了由它来维护关联关系,所以他要先存主表class, 
      // 再回来存副表student,但是student发现它的classes为null,就把class_id字段设为了空. 
        
         
      session.save(classes); 
*/
        
/*      Classes classes=new Classes();//情况3 
      classes.setName("不一班"); 
        
      Student student1=new Student(); 
      student1.setName("志鹏"); 
      student1.setClasses(classes); 
        
      Student student2=new Student(); 
      student2.setName("有朋"); 
      student2.setClasses(classes); 
        
      Set<Student> students=new HashSet<Student>(); 
      students.add(student1); 
      students.add(student2); 
        
      classes.setStudents(students); 
      //同样能正确保存.sql语句如下: 
      //如果<set>标签中有inverse="true",cascade="save-update": 
      //Hibernate: insert into sxt_hibernate_class (name, id) values (?, ?) 
      //Hibernate: insert into sxt_hibernate_student (name, class_id, id) values (?, ?, ?) 
      //Hibernate: insert into sxt_hibernate_student (name, class_id, id) values (?, ?, ?) 
      //这种情况student的class_id也有了,因为在插入student时,由student来维护了关系,而它引用的class已经是持久化的了. 
         
      //存储过程是这样的:存classes时,由于有cascade="save-update",它会先触发存储student;    
      // 而在存储student时,inverse="true"指明了由它来维护关联关系,所以他要先存主表class,再回来存副表student 
      session.save(classes);*/
 
       /** 
        * 小结:情况1是我们提倡的; 
        *         情况2.1虽然也能实现正确插入,但是效率低; 
        *         情况2.2显然是错误的; 
        *         情况3虽然也能实现,并且效率也不低,但是编程上比较麻烦. 
        */
 
        
       /** 
        * 测试加载数据 
        */
 
      Student student=(Student)session.get(Student. class, 3); 
      System.out.println(student); 
      System.out.println(student.getClasses()); 
      t.commit(); 
    }  catch (HibernateException e) { 
      e.printStackTrace(); 
      t.rollback(); 
    }  finally { 
      HibernateUtils.closeSession(session); 
    } 
  } 
}
     本文转自NightWolves 51CTO博客,原文链接: http://blog.51cto.com/yangfei520/275947 ,如需转载请自行联系原作者



相关文章
|
4月前
|
SQL 缓存 Java
Hibernae - 双向多对一关联关系映射
Hibernae - 双向多对一关联关系映射
33 0
|
4月前
|
SQL Java 数据库
JPA - 单向一对多映射
JPA - 单向一对多映射
35 2
|
4月前
|
Java uml
JPA - 单向多对一映射
JPA - 单向多对一映射
39 0
|
SQL Oracle Java
hibernate(四) 双向多对多映射关系
现在继上一章节的一对多的映射关系讲解后,今天来讲讲多对多的映射关系把,明白了一对多,多对多个人感觉还是比较容易的,需要理清楚其数据库关系图,那么你就拿下了它。映射文件的配置还是那么些死东西。
136 0