hibernate学习之表关联和级联

班级学生一对多表关联

  • 建立关联关系的话首先至少要有两个表,那就要有两个实体类,通常是一对多的关系,比如学生和班级,可以在其中一个类加入另一个类的实例,比如在学生中包含班级这个类(如果是班级中包含学生的话那应该是一个班级包含一个学生集合)

      public class Student {
    
          private long id;
          private String name;
          private Class c; //学生只有一个班级,多对一
     }
    
  • 映射文件中加入外键声明,多的这个表一定要加

      <!--在学生表中插入一个外键-->
      <many-to-one name="c" column="classId" class="com.java1234.model.Class" cascade="save-update"></many-to-one>
    
  • 一的这边也可以声明和多的之间的关联(不是必要)

      //类
      public class Class {
    
          private long id;
          private String name;
          private Set<Student> students=new HashSet<Student>();
     }
     
     //映射文件
     <!-- 因为是一对多,所以class表不会多出下面字段,只是建立一种关联而已,不写也可以(写了的话获取班级的同时会自动获取学生集合),但学生表那边一定要写 -->
      <set name="students" cascade="save-update" inverse="true"> <!-- 加上save-update可以在只保存class的情况下顺便保存student;加上inverse就能在多的一端维护外键;加上cascade="delete"可以进行级联删除 -->
      	<key column="classId"></key> <!-- 外键名 --> 
      	<one-to-many class="com.java1234.model.Student"/>
      </set>
    
    • 比如上面这个set集合如果不设置的话,那么下面打印的将是0,因为班级获取不到学生

        public void testInversse() {
        Class c=(Class)session.get(Class.class, Long.valueOf(1));
        Set<Student> students=c.getStudents();
        System.out.println(students.size());
       }
      
  • 最后插入数据的时候要在学生中设置好班级

      Class c=new Class();
      c.setName("08计本");
      session.save(c);
      
      Student s1=new Student();
      s1.setName("张三");
      s1.setC(c);
      
      Student s2=new Student();
      s2.setName("李四");
      s2.setC(c);
      
      session.save(s1);
      session.save(s2);
    
  • 经过上面学生类和学生映射文件这两步,学生这个表就会自动关联到班级表的主键。

级联

  • 学生映射文件中,在标签里面,cascade默认是“none”,假如我们希望在持久化多的一端时自动级联保存和更新一的一端,我们可以把cascade设置成“save-update”。那么这个class自己不保存也可以跟着引用了它的student保存下来。反过来,在班级映射文件中加入该标签,则可以使student随着class保存而保存。

      Class c=new Class();
      c.setName("08计本");
      // session.save(c); 不保存,在<many-to-one>标签中加个属性cascade属性即可随多的一方(Student)保存
      
      Student s1=new Student();
      s1.setName("张三");
      s1.setC(c);
      
      Student s2=new Student();
      s2.setName("李四");
      s2.setC(c);
      
      session.save(s1);
      session.save(s2);
    

inverse属性

  • 剪除多余hql,提高性能

      <set name="students" cascade="save-update" inverse="true"> <!-- 加上save-update可以在只保存class的情况下顺便保存student;加上inverse就能在多的一端维护外键;加上cascade="delete"可以进行级联删除 -->
      	<key column="classId"></key> <!-- 外键名 --> 
      	<one-to-many class="com.java1234.model.Student"/>
      </set>
    
  • 比如上面班级配置文件中的inverse属性,加上之后可以提高以下程序的性能

      //先添加两条没有关联的数据
      @Test
      public void testAdd() {
          Class c=new Class();
          c.setName("09计本");
      
          Student s1=new Student();
          s1.setName("王五");
      
          session.save(c);
          session.save(s1);
      }
      
      //把这两条数据查出来之后再建立联系
      @Test
      public void testInversse() {
          Class c=(Class)session.get(Class.class, Long.valueOf(1));
          Student s=(Student)session.get(Student.class, Long.valueOf(1));
      
          //加了inverse之后可以使第二行不生效(因为它本来就没用,除了多一句多余的hql拖慢性能)提高性能,一般都是在多的一端保存即可
          s.setC(c); //在学生中添加班级,会在学生表中增加班级外键
          c.getStudents().add(s); //在班级中添加学生,会在学生表中增加学生外键
          //这样就会生成hql,在这个学生中加入这个班级的外键
      }
    

级联删除

  • 删除被关联的表时顺便删除父表

      /*
       * 这样运行应该是报错的,因为class表被关联,加上属性cascade="delete"后才能进行级联删除,将学生表记录一并删掉
      */
      @Test
      public void testDeleteClassCascade() {
          Class c=(Class)session.get(Class.class, Long.valueOf(1));
          session.delete(c);
      }
    

自身关联

  • 自身字段关联自身字段,比如下面一个菜单的例子

    • 数据库

      //类
      public class Node {
    
          private long id;
          private String name;
    
          private Node parentNode; //父节点
    
          private Set<Node> childNodes=new HashSet<Node>(); //子节点
     }
     
     //映射文件
     <!-- 自身外键关联 -->
      <many-to-one name="parentNode" column="parentId" class="com.java1234.model.Node" cascade="save-update"></many-to-one>
      <set name="childNodes" inverse="true"> <!-- 加上save-update可以在只保存class的情况下顺便保存student;加上inverse就能在多的一端维护外键;加上cascade="delete"可以进行级联删除 -->
      	<key column="parentId"></key> <!-- 外键名  -->
      	<one-to-many class="com.java1234.model.Node"/>
      </set>
      
      //保存数据
      @Test
      public void testSaveMenu() {
          Node node=new Node();
          node.setName("根结点");
      
          Node subNode1=new Node();
          subNode1.setName("子结点1");
      
          Node subNode2=new Node();
          subNode2.setName("子结点2");
      
          subNode1.setParentNode(node);
          subNode2.setParentNode(node);
      
          session.save(subNode1);
          session.save(subNode2);
      }
    

代码实例:eclipse->HibernateCrud

猜你喜欢

转载自blog.csdn.net/jiachunchun/article/details/89670750