• 六、hibernate表与表之间的关系(多对多关系)


    多对多关系

    创建实体类和对应映射文件

    Student.java

     1 package com.qf.entity;
     2 
     3 import java.util.HashSet;
     4 import java.util.Set;
     5 
     6 public class Student {
     7 
     8     private Long sid;
     9     private String sname;
    10     //一个学生可以有很多个老师
    11     private Set<Teacher> teachs = new HashSet<>();
    12 
    13     public Long getSid() {
    14         return sid;
    15     }
    16     public void setSid(Long sid) {
    17         this.sid = sid;
    18     }
    19     
    20     public String getSname() {
    21         return sname;
    22     }
    23     public void setSname(String sname) {
    24         this.sname = sname;
    25     }
    26     
    27     public Set<Teacher> getTeachs() {
    28         return teachs;
    29     }
    30     public void setTeachs(Set<Teacher> teachs) {
    31         this.teachs = teachs;
    32     }
    33     @Override
    34     public String toString() {
    35         return "Student [sid=" + sid + ", sname=" + sname + ", teachs=" + teachs + "]";
    36     }
    37     
    38 }
    View Code

    Student.hbm.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    	<!-- 配置表与实体的映射关系 -->
    	<class name="com.qf.entity.Student" table="student">
    		<id name="sid" column="sid">
    			<generator class="native"></generator>
    		</id>
    		<property name="sname" column="sname"/>
    		<set name="teachs" table="teach_stu" >
    			<key column="sid"/>
    			<many-to-many class="com.qf.entity.Teacher" column="tid" />
    		</set>
    	</class>
    </hibernate-mapping>

    Teacher.java

     1 package com.qf.entity;
     2 
     3 import java.util.HashSet;
     4 import java.util.Set;
     5 
     6 public class Teacher {
     7     private long tid;
     8     private String tname;
     9     private String course;
    10     //一个教师可以有多个学生
    11     private Set<Student> stus = new HashSet<Student>();
    12     
    13     public Set<Student> getStus() {
    14         return stus;
    15     }
    16     public void setStus(Set<Student> stus) {
    17         this.stus = stus;
    18     }
    19     public long getTid() {
    20         return tid;
    21     }
    22     public void setTid(long tid) {
    23         this.tid = tid;
    24     }
    25     public String getTname() {
    26         return tname;
    27     }
    28     public void setTname(String tname) {
    29         this.tname = tname;
    30     }
    31     public String getCourse() {
    32         return course;
    33     }
    34     public void setCourse(String course) {
    35         this.course = course;
    36     }
    37     @Override
    38     public String toString() {
    39         return "Teacher [tid=" + tid + ", tname=" + tname + ", course=" + course + "]";
    40     }
    41     
    42     
    43 }
    View Code

    Teacher.hbm.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    	<!-- 配置表与实体的映射关系 -->
    	<class name="com.qf.entity.Teacher" table="teacher">
    		<id name="tid" column="tid">
    			<generator class="native"/>
    		</id>
    		<property name="tname" column="tname"/>
    		<property name="course" column="course"/>
    		<set name="stus" table="teach_stu">
    			<key column="tid"></key>
    			<many-to-many class="com.qf.entity.Student" column="sid"/>
    		</set>
    	</class>
    </hibernate-mapping> 

    测试

    @Test
    public void test() {
    	Session session = SessionFactoryUtil.getSession();
    	Transaction tx = session.beginTransaction();
    	
    	//创建两个教师对象,三个学生对象
    	//学生选择老师
    	Teacher t1 = new Teacher();
    	t1.setTname("张老师");
    	Teacher t2 = new Teacher();
    	t2.setTname("李老师");
    	Student s1 = new Student();
    	s1.setSname("张三");
    	Student s2 = new Student();
    	s2.setSname("李四");
    	Student s3 = new Student();
    	s3.setSname("王五");
    	
    	//学生和老师之间建立双向关系
    	//多对多关系建立双向关系后,双方必须有一方放弃维护外键关系权(inverse),否则会因为中间表主键重复抛出异常
    	s1.getTeachs().add(t1);
    	s1.getTeachs().add(t2);
    	s3.getTeachs().add(t1);
    	s2.getTeachs().add(t2);
    	t1.getStus().add(s1);
    	t1.getStus().add(s3);
    	t2.getStus().add(s2);
    	t2.getStus().add(s1);
    	
    	session.save(s1);
    	session.save(s2);
    	session.save(s3);
    	session.save(t1);
    	session.save(t2);
    	
    	tx.commit();
    }

    -------------------------------------console-------------------------------------

    Hibernate: alter table teach_stu drop foreign key FKsrw3nh8oe5xhmqqxm2qng952t
    Hibernate: alter table teach_stu drop foreign key FKtc48sy6cweqkufd4c777i8vsp
    Hibernate: drop table if exists student
    Hibernate: drop table if exists teach_stu
    Hibernate: drop table if exists teacher
    Hibernate: create table student (sid bigint not null auto_increment, sname varchar(255), primary key (sid))
    Hibernate: create table teach_stu (tid bigint not null, sid bigint not null, primary key (sid, tid))
    Hibernate: create table teacher (tid bigint not null auto_increment, tname varchar(255), course varchar(255), primary key (tid))
    Hibernate: alter table teach_stu add constraint FKsrw3nh8oe5xhmqqxm2qng952t foreign key (sid) references student (sid)
    Hibernate: alter table teach_stu add constraint FKtc48sy6cweqkufd4c777i8vsp foreign key (tid) references teacher (tid)
    11:21:37,135  INFO SchemaExport:464 - HHH000230: Schema export complete
    Hibernate: insert into student (sname) values (?)
    Hibernate: insert into student (sname) values (?)
    Hibernate: insert into student (sname) values (?)
    Hibernate: insert into teacher (tname, course) values (?, ?)
    Hibernate: insert into teacher (tname, course) values (?, ?)
    Hibernate: insert into teach_stu (sid, tid) values (?, ?)
    Hibernate: insert into teach_stu (sid, tid) values (?, ?)
    Hibernate: insert into teach_stu (sid, tid) values (?, ?)
    Hibernate: insert into teach_stu (sid, tid) values (?, ?)
    Hibernate: insert into teach_stu (tid, sid) values (?, ?)
    11:21:37,270  WARN SqlExceptionHelper:127 - SQL Error: 1062, SQLState: 23000
    11:21:37,271 ERROR SqlExceptionHelper:129 - Duplicate entry '1-1' for key 'PRIMARY'
    11:21:37,271  INFO AbstractBatchImpl:193 - HHH000010: On release of batch it still contained JDBC statements
    11:21:37,272 ERROR SessionImpl:2994 - HHH000346: Error during managed flush [could not execute statement]

    原因

      测试中因为建立了双向关系,所以teacher和student都会去维护外键,导致相同的(1,1)会两次插入中间关系表teach_stu中

    解决办法

      一方放弃维护外键关系权。一般被动主体放弃维护外键权,比如学生选择老师,老师放弃维护外键权;老师选择学生,学生放弃维护外键权

    修改Teacher.hbm.xml:<set name="stus" table="teach_stu" inverse="true">

    -------------------------------------console-------------------------------------

    Hibernate: alter table teach_stu drop foreign key FKsrw3nh8oe5xhmqqxm2qng952t
    Hibernate: alter table teach_stu drop foreign key FKtc48sy6cweqkufd4c777i8vsp
    Hibernate: drop table if exists student
    Hibernate: drop table if exists teach_stu
    Hibernate: drop table if exists teacher
    Hibernate: create table student (sid bigint not null auto_increment, sname varchar(255), primary key (sid))
    Hibernate: create table teach_stu (tid bigint not null, sid bigint not null, primary key (sid, tid))
    Hibernate: create table teacher (tid bigint not null auto_increment, tname varchar(255), course varchar(255), primary key (tid))
    Hibernate: alter table teach_stu add constraint FKsrw3nh8oe5xhmqqxm2qng952t foreign key (sid) references student (sid)
    Hibernate: alter table teach_stu add constraint FKtc48sy6cweqkufd4c777i8vsp foreign key (tid) references teacher (tid)
    11:30:43,077  INFO SchemaExport:464 - HHH000230: Schema export complete
    Hibernate: insert into student (sname) values (?)
    Hibernate: insert into student (sname) values (?)
    Hibernate: insert into student (sname) values (?)
    Hibernate: insert into teacher (tname, course) values (?, ?)
    Hibernate: insert into teacher (tname, course) values (?, ?)
    Hibernate: insert into teach_stu (sid, tid) values (?, ?)
    Hibernate: insert into teach_stu (sid, tid) values (?, ?)
    Hibernate: insert into teach_stu (sid, tid) values (?, ?)
    Hibernate: insert into teach_stu (sid, tid) values (?, ?)

    数据成功插入数据库

    级联保存

    保存学生级联保存教师

    主体是学生,所以修改学生的映射文件Student.hbm.xml

    <hibernate-mapping>
    	<!-- 配置表与实体的映射关系 -->
    	<class name="com.qf.entity.Student" table="student">
    		<id name="sid" column="sid">
    			<generator class="native"></generator>
    		</id>
    		<property name="sname" column="sname"/>
    		<set name="teachs" table="teach_stu" cascade="save-update" >
    			<key column="sid"/>
    			<many-to-many class="com.qf.entity.Teacher" column="tid" />
    		</set>
    	</class>
    </hibernate-mapping>

    测试方法

    @Test
    public void test() {
    	Session session = SessionFactoryUtil.getSession();
    	Transaction tx = session.beginTransaction();
    	
    	//保存学生级联保存教师
    	Teacher t1 = new Teacher();
    	t1.setTname("张老师");
    	Student s1 = new Student();
    	s1.setSname("张三");
    	
    	t1.getStus().add(s1);
    	s1.getTeachs().add(t1);
    	
    	session.save(s1);
    	
    	tx.commit();
    }

    -------------------------------------console-------------------------------------

    Hibernate: create table student (sid bigint not null auto_increment, sname varchar(255), primary key (sid))
    Hibernate: create table teach_stu (tid bigint not null, sid bigint not null, primary key (sid, tid))
    Hibernate: create table teacher (tid bigint not null auto_increment, tname varchar(255), course varchar(255), primary key (tid))
    Hibernate: alter table teach_stu add constraint FKsrw3nh8oe5xhmqqxm2qng952t foreign key (sid) references student (sid)
    Hibernate: alter table teach_stu add constraint FKtc48sy6cweqkufd4c777i8vsp foreign key (tid) references teacher (tid)
    14:22:37,418  INFO SchemaExport:464 - HHH000230: Schema export complete
    Hibernate: insert into student (sname) values (?)
    Hibernate: insert into teacher (tname, course) values (?, ?)
    Hibernate: insert into teach_stu (sid, tid) values (?, ?

    级联删除(一般不使用)

    想以哪一方为主体删除另一方,就在哪一方映射文件中配置cascade属性:

      <set name="teachs" table="teach_stu" cascade="delete" >

  • 相关阅读:
    linux机器间建立信任关系
    Linux shell逐行读取文件的方法
    linux强制用户下线命令
    Linux用户都应该了解的命令行省时技巧
    常用Linux Shell命令组合
    利用TensorFlow object_detection API 训练自己的检测器
    逻辑回归的梯度下降计算
    Android内存优化(使用SparseArray和ArrayMap代替HashMap)
    卷积的三种模式:full、same、valid + 卷积输出size的计算
    关于转置卷积(反卷积)的理解
  • 原文地址:https://www.cnblogs.com/qf123/p/10173799.html
Copyright © 2020-2023  润新知