Hibernate多表关系配置

#2020云栖大会#阿里云海量offer来啦!投简历、赢阿里云限量礼品及阿里云ACA认证免费考试资格!>>> hot3.png

Hibernate多表关系配置


8b6e09bfccdb5ff59b1336c18b8649df112.png

1.表的关系

2.一对多配置

3.级联操作

4.多对多配置

5.多对多操作

035833da71e61bc4aad9101583bd36f8bb3.png 1 表的关系

表之间的关系

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


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


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



表之间关系建表原则


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


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


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


79b295ebb52510247a8eda48ee95f48bccd.gif


2 一对多配置


1.建表(班级、学生)


class_idclass_namenumbers
stu_idstu_namestu_ageclass_id



2.建立ORM

domain类

@Getter@Setterpublic class Classes {    private Integer class_id;    private String class_name;    private Integer class_student;    //一个班级包含多个学生    private Set<Student> students = new HashSet<>();}
@Setter@Getterpublic 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-namenumbers
1
c1null
2
c2
null
3
c3
null
stu_id
stu_name
stu_ageclass_id
1
s1
null
1
2
s2
null
1
3
s3
null
2
默认是先保存各自的内容,再建立连接(添上外键),删除也是先去掉外键再删除。接下来通过级联操作实现关联关系表同步更新 79b295ebb52510247a8eda48ee95f48bccd.gif


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"


79b295ebb52510247a8eda48ee95f48bccd.gif




4 多对多配置

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



建表


课表
course_id
course_name
学生表
stu_idstu_namestu_ageclass_id
c-s关系表
stu_idcourse_id



建立ORM


domain类

@Setter@Getterpublic class Student {    private Integer stu_id;    private String stu_name;    private Integer stu_age;    //一个学生有多门课程    private set<Course> courses;}
@Setter@Getterpublic 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"/>



编写测试

@Testpublic 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();}

9fbc7a1ffca1a1d8686ff45c9132e6892a6.png

7ed862d8e1c70e8b7bfbc144b5df73df554.png

4b94dac8b4938337a715cc2ca3ca209d65e.png


79b295ebb52510247a8eda48ee95f48bccd.gif



5 多对多操作

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


给上面王五添加数学课

@Testpublic 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();}

4fa3bb2764d8b75112c130eddaea68086f8.png


其他也是一样


给王五删除数学课

@Testpublic 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();}


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

@Testpublic 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();}





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


79b295ebb52510247a8eda48ee95f48bccd.gif






b2b8ec58d3e2a6f829c55ce8cb32b913d39.png

44c34df92298bcd8951b2860f841f317184.jpg

它,

不仅仅是一个码





本文分享自微信公众号 - IT那个小笔记(qq1839646816)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

posted @ 2019-09-09 22:33  木瓜煲鸡脚  阅读(48)  评论(0)    收藏  举报