`
KuangYeYaZi
  • 浏览: 52500 次
文章分类
社区版块
存档分类
最新评论

一对多关联映射(单向)

 
阅读更多
“一对多”,顾名思义,是由“一”的一端加载“多”的一端,关系交由“一”来维护。反映在Java代码中就是在“一”的一端中持有“多”一端的集合,而hibernate把这种关系反映到数据库的策略是在“多”一端的表上加上一个外键指向“一”一端表。显现,其实这采用的还是“多対一”的映射原理。
     但是,在“一”一端维护关系是我们不提倡的,因为它有不可避免的缺点,即级联插入数据的时候要先插“多”一端,这样造成了两方面的不妥:1.如果我们把“多”一端的外键必须添加非空约束,将导致数据不能插入;2.即使外键不设置为非空,在插入“多”一端数据时外键将暂时为空( 因为此时它所引用的“一”记录还没有插入),而只有等到它所引用的“一”记录插入后,再发出update语句修改外键,这样的效率必然降低。
     不管怎样,还是来看看我的Classes和Student怎么做的吧。
1.实体模型:


 
 
2.关系模型:


 
 
3.实体类:
   Student.java
public class Student { 
  private Integer id; 
  private String name; 
  //一系列的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> 
  </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> 
    <!-- 配置集合属性 --> 
    <set name="students" cascade="save-update"> 
      <!-- 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 { 
      /** 
        * 测试插入数据 
        */
 
      /* 
        * Student student1=new Student();    
        * 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); 
        * //存储不成功.报错:org.hibernate.TransientObjectException 
        * //因为此时student对象还没有持久化,classes引用了瞬时对象student1,student2 
        * session.save(classes); 
        */
 

        
        Student student1=new Student(); student1.setName("奇隆"); 
        //session.save(student1);//先把student对象持久化 
         
        Student student2=new Student(); 
        student2.setName("有朋");    
        //session.save(student2); 
         
        Set<Student> students=new HashSet<Student>(); 
        students.add(student1); 
        students.add(student2); 
         
        Classes classes=new Classes(); 
        classes.setName("不一班"); 
        classes.setStudents(students); 
        //存储成功.sql语句如下: 
        /* 
        Hibernate: insert into sxt_hibernate_class (name, id) values (?, ?) 
        Hibernate: insert into sxt_hibernate_student (name, id) values (?, ?) 
        Hibernate: insert into sxt_hibernate_student (name, id) values (?, ?) 
        Hibernate: update sxt_hibernate_student set class_id=? where id=? 
        Hibernate: update sxt_hibernate_student set class_id=? where id=? */
 
        //可见在存储class之后,发出两个update语句,把它的两个student对象的class_id更新了. 
        //这是因为关系由"一"的一端维护(即class维护关系).这显然会降低效率. 
        //所以对于一对多,我们一般把关系交给"多"的一端维护.    
        session.save(classes); 
         
      /** 
        * 测试加载数据 
        */
 
/*      Classes classes = (Classes) session.load(Classes.class, 3); 
      System.out.println(classes); 
      Set<Student> students = classes.getStudents(); 
      for (Iterator<Student> stus = students.iterator(); stus.hasNext();) { 
        System.out.println(stus.next()); 
      }*/
 
      t.commit(); 
    } catch (HibernateException e) { 
      e.printStackTrace(); 
      t.rollback(); 
    } finally { 
      HibernateUtils.closeSession(session); 
    } 
  } 

} 

本文出自 “夜狼” 博客,请务必保留此出处http://yangfei520.blog.51cto.com/1041581/275656

 

  • 大小: 8.6 KB
  • 大小: 7.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics