­

Hibernate多表关系配置

  • 2019 年 10 月 4 日
  • 筆記

Hibernate多表关系配置

1.表的关系

2.一对多配置

3.级联操作

4.多对多配置

5.多对多操作

1

表的关系

表之间的关系

一对多(一个部门有多个员工,一个员工只能属于某一个部门)

多对多(一个老师教多个学生,一个学生可以被多个老师教)

一对一(一个公司只能对应一个注册地址)

表之间关系建表原则

一对多在多的一方创建一个外键,指向一的一方的主键)

多对多(创建一个中间表,中间表至少有两个字段,分别作为外键指向多对多双方的主键)

一对一(唯一外键对应或主键对应)

2

一对多配置

1.建表(班级、学生)

class_id

class_name

numbers

stu_id

stu_name

stu_age

class_id

2.建立ORM

domain类

@Getter@Setter  public class Classes {      private Integer class_id;      private String class_name;      private Integer class_student;      //一个班级包含多个学生      private Set<Student> students = new HashSet<>();  }
@Setter@Getter  public class Student {      private Integer stu_id;      private String stu_name;      private Integer stu_age;      //一个学生属于一个班级      private Classes stu_class;  }

映射文件

映射文件中普通字段段的配置不用写上外键,在一的一方配置文件写上set标签name属性为关联属性名,里面还有key标签有column属性关系中的外键即另一个表的外键字段名,还有一个标签one-to-many写上另一表的domain类全路径。在多的一方只有一个many-to-one标签里面name属性也是关联属性名,class属性关系表它的domain地址,还有一个column外键

<hibernate-mapping>      <class name="com.hao.domain.Classes" table="classes">            <id name="class_id" >              <generator class="identity"/>          </id>          <property name="class_name"/>          <set name="students">              <key column="class_id"></key>              <one-to-many class="com.hao.domain.Student"></one-to-many>          </set>      </class>  </hibernate-mapping>
<hibernate-mapping>  <class name="com.hao.domain.Student" table="student">        <id name="stu_id">          <generator class="identity"/>      </id>      <property name="stu_name" />      <property name="stu_age" />      <many-to-one name="stu_class" class="com.hao.domain.Classes" column="class_id" lazy="false"></many-to-one>  </class>  </hibernate-mapping>

3.添加核心配置文件

<mapping resource="com/hao/domain/Student.hbm.xml"/>  <mapping resource="com/hao/domain/Classes.hbm.xml"/>

4.编写测试类

    public void saveTest() {          Session session = HibernateUtil.openSession();          Transaction tra = session.beginTransaction();          //创建三个班级          Classes c1 = new Classes();          Classes c2 = new Classes();          Classes c3 = new Classes();          c1.setClass_name("c1");          c2.setClass_name("c2");          c3.setClass_name("c3");          //创建三个学生          Student s1 = new Student();          Student s2 = new Student();          Student s3 = new Student();          s1.setStu_name("张三");          s2.setStu_name("李四");          s3.setStu_name("王五");          //班级1添加两个学生,班级2添加一个学生          c1.getStudents().add(s1);          c1.getStudents().add(s2);          c2.getStudents().add(s3);          //保存全部          session.save(s1);          session.save(s2);          session.save(s3);          session.save(c1);          session.save(c2);          session.save(c3);            tra.commit();      }

结果

class_id

class-name

numbers

1

c1

null

2

c2

null

3

c3

null

stu_id

stu_name

stu_age

class_id

1

s1

null

1

2

s2

null

1

3

s3

null

2

默认是先保存各自的内容,再建立连接(添上外键),删除也是先去掉外键再删除。接下来通过级联操作实现关联关系表同步更新

3

级联操作

按照上面的操作保存3个班级3个学生,共六条保存

理论上只保存一边是可行的。

比如只保存班级c1、c2、c3,它们添加了s1、s2、s3。

所以添加班级也会在学生表中添加对应的记录。

但是实际上会报错——瞬时对象异常

这是因为保存的对象关联了处于瞬时态的对象

我们可以在配置文件中去开启级联操作

在哪个配置文件去开启,就在它对应的domain保存时才有级联

在Classes的映射文件去添加cascade,保存classes时就会级联保存不用再单独去保存student,关联信息本来在classes就有

 <set name="students" cascade="save-update">     <key column="class_id" ></key>     <one-to-many class="com.hao.domain.Student" ></one-to-many>   </set>

还可以写在Student的映射文件,这样保存student就会同时保存关联的classes信息

<many-to-one  cascade="save-update" name="stu_class" class="com.hao.domain.Classes" column="class_id" lazy="false" ></many-to-one>

在更新时也会有级联操作,当classes移除一个学生,那么student表会变

还有删除,当删除一个班级,那么student表中属于这个班的student也会全删掉

cascade="delete"

4

多对多配置

配置和一对多一样,只是set标签中多一个table属性值为中间关系表的表名

建表

course_id

course_name

stu_id

stu_name

stu_age

class_id

stu_id

course_id

建立ORM

domain类

@Setter@Getter  public class Student {      private Integer stu_id;      private String stu_name;      private Integer stu_age;      //一个学生有多门课程      private set<Course> courses;  }
@Setter@Getter  public class Course {      private Integer Course_id;      private String Course_name;      //一个课程有众多学生学习      private set<Student> students;  }

映射文件

<set name="courses" table="c-s" cascade="save-update,delete">    <key column="stu_id"></key>    <many-to-many class="com.hao.domain.Course" column="course_id"></many-to-many>  </set>
<set name="students" table="c-s">    <key column="course_id"></key>    <many-to-many class="com.hao.domain.Student" column="stu_id"></many-to-many>  </set>

最后再在核心配置文件加载上映射文件

<mapping resource="com/hao/domain/Course.hbm.xml"/>

编写测试

@Test  public void manytomany(){    Course c1 = new Course();    Course c2 = new Course();    Course c3 = new Course();    c1.setCourse_name("语文");    c2.setCourse_name("数学");    c3.setCourse_name("英语");      Student s1 = new Student();    Student s2= new Student();    Student s3 = new Student();    s1.setStu_name("张三");    s2.setStu_name("李四");    s3.setStu_name("王五");      c1.getStudents().add(s1);    c1.getStudents().add(s2);    c1.getStudents().add(s3);    c2.getStudents().add(s1);    c3.getStudents().add(s2);    c3.getStudents().add(s3);      Session session = HibernateUtil.openSession();    Transaction tra = session.beginTransaction();    session.save(c1);    session.save(c2);    session.save(c3);    tra.commit();  }

5

多对多操作

对多对的操作双方的关系都在中间表上,都在各自得关联集合中。所以它们得操作就是操作集合

给上面王五添加数学课

@Test  public void manytomany(){    Session session = HibernateUtil.openSession();    Transaction tra = session.beginTransaction();    //获取王五    Student stu = session.get(Student.class,1);    //获取数学课    Course course = session.get(Course.class,2)    //修改集合    stu.getCourses().add(course);    tra.commit();  }

其他也是一样

给王五删除数学课

@Test  public void manytomany(){    Session session = HibernateUtil.openSession();    Transaction tra = session.beginTransaction();    //获取王五    Student stu = session.get(Student.class,1);    //获取数学课    Course course = session.get(Course.class,2)    //修改集合    stu.getCourses().remove(course);    tra.commit();  }

给王五把英语课改为数学课(其实就是前面的删除和添加)

@Test  public void manytomany(){    Session session = HibernateUtil.openSession();    Transaction tra = session.beginTransaction();    //获取王五    Student stu = session.get(Student.class,1);    //获取英语课    Course course1 = session.get(Course.class,3);    //获取数学课    Course course2 = session.get(Course.class,2);    //修改集合    stu.getCourses().remove(course1);    stu.getCourses().add(course2);    tra.commit();  }

特别注意:事务提交、建表引擎(坑)