六、hibernate表与表之间的关系(多对多关系)
多对多关系
创建实体类和对应映射文件
Student.java
package com.qf.entity; import java.util.HashSet;
import java.util.Set; public class Student { private Long sid;
private String sname;
//一个学生可以有很多个老师
private Set<Teacher> teachs = new HashSet<>(); public Long getSid() {
return sid;
}
public void setSid(Long sid) {
this.sid = sid;
} public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
} public Set<Teacher> getTeachs() {
return teachs;
}
public void setTeachs(Set<Teacher> teachs) {
this.teachs = teachs;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", teachs=" + teachs + "]";
} }
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
package com.qf.entity; import java.util.HashSet;
import java.util.Set; public class Teacher {
private long tid;
private String tname;
private String course;
//一个教师可以有多个学生
private Set<Student> stus = new HashSet<Student>(); public Set<Student> getStus() {
return stus;
}
public void setStus(Set<Student> stus) {
this.stus = stus;
}
public long getTid() {
return tid;
}
public void setTid(long tid) {
this.tid = tid;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
@Override
public String toString() {
return "Teacher [tid=" + tid + ", tname=" + tname + ", course=" + course + "]";
} }
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" >
六、hibernate表与表之间的关系(多对多关系)的更多相关文章
- 【Java EE 学习 46】【Hibernate学习第三天】【多对多关系映射】
一.多对多关系概述 以学生和课程之间的关系为例. 1.在多对多关系中涉及到的表有三张,两张实体表,一张专门用于维护关系的表. 2.多对多关系中两个实体类中应当分别添加对方的Set集合的属性,并提供se ...
- day 7-15 表与表之间的关系
一. 前言 表与 表之间有3种对应关系,分别是: 多对一:一张表中的一个字段中的多个值对应另外一张表中的一个字段值.(多个学生,可以学习同一门课程) 多对多;一张表中的一个字段值对应另外一张表中的多个 ...
- day 69 orm操作之表关系,多对多,多对一(wusir总结官网的API)
对象 关系 模型 wusir博客地址orm官网API总结 django官网orm-API orm概要: ORM 跨表查询 class Book(models.Model): title = mod ...
- EF Core中如何设置数据库表自己与自己的多对多关系
本文的代码基于.NET Core 3.0和EF Core 3.0 有时候在数据库设计中,一个表自己会和自己是多对多关系. 在SQL Server数据库中,现在我们有Person表,代表一个人,建表语句 ...
- Django中多对多关系的orm表设计
作者的管理 1.设计表结构 出版社 书籍 作者 一个出版社出版多个书籍 1对多 书籍和作者的关系:一个作者写多本书,一本书可以是多个作者写.多对多 1)创建一张表,表中多对多的数据关系.使用 多对多 ...
- [MySQL数据库之表的约束条件:primary key、auto_increment、not null与default、unique、foreign key:表与表之间建立关联]
[MySQL数据库之表的约束条件:primary key.auto_increment.not null与default.unique.foreign key:表与表之间建立关联] 表的约束条件 约束 ...
- django ORM模型表的一对多、多对多关系、万能双下划线查询
一.外键使用 在 MySQL 中,如果使用InnoDB引擎,则支持外键约束.(另一种常用的MyIsam引擎不支持外键) 定义外键的语法为fieldname=models.ForeignKey(to_c ...
- 【Hibernate】多对多关系的表达
User.hbm.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate ...
- 07 Mybatis的多表查询1----1对多和多对1---@Results注解用法总结
1.表与表之间的关系及其举例 表之间的关系有4种:一对多.多对一.一对一.多对多. 举例: (1)用户和订单就是一对多 一个用户可以下多个订单 (2)订单和用户就是多对一 多个订单属于同一个用户 (3 ...
随机推荐
- XMPP即时通讯协议使用(八)——基于订阅发布实现消息流转业务泳道图
- Spring Boot 项目 Maven 配置
在配置基于Maven的Spring Boot项目的过程中,打包运行出现了一系列错误. 比如: mvn 中没有主清单属性.java.lang.NoClassDefFoundError: org/spri ...
- 125-FMC125-两路125Msps AD,两路160Msps DA FMC子卡模块
FMC125-两路125Msps AD,两路160Msps DA FMC子卡模块 1.板卡概述 该板卡可实现2路14bit 250Msps AD 和2路16bit 160MspsDA功能,FMC连接 ...
- 《YC创业营:硅谷顶级创业孵化器如何改变世界》:YC2011批量天使投资记录 三星推荐
这个YC创业营是一个硅谷的天使投资基金,每年两次批量投资创业公司.本书说的是2011年YC批量选择了64个创业团队,让他们集中到硅谷办公3个月,给他们创业指导,帮他们找A轮投资. YC创始人偏爱25岁 ...
- Codeforces 633F 树的直径/树形DP
题意:有两个小孩玩游戏,每个小孩可以选择一个起始点,并且下一个选择的点必须和自己选择的上一个点相邻,问两个选的点权和的最大值是多少? 思路:首先这个问题可以转化为求树上两不相交路径的点权和的最大值,对 ...
- $Noip$前的小总结哦
考试失误点与积累 有点不知道该干嘛了,状态有点差,写点东西.(后面可能会加更一点东西?) 常规错误 \(1.\) 数组开小 \(2.\) \(int\)和\(longlong\) \(3.\) 开某题 ...
- C#调用谷歌翻译API
原资料为网上找到的原稿为:http://www.cnblogs.com/marso/p/google_translate_api.html(此处只做个人笔记参考) 主要分两块:通过WebRequest ...
- 【优化】Java开发中注意内存问题,影响JVM
1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 第一,控制资源的使用,通过线程同步来控 ...
- 【HDU6609】Find the answer【线段树】
题目大意:给你一个序列,对于每个i,你可以选择1~i-1中任意多的数并将它删去,剩余的数(包括i)∑≤m,问对于每个i最少删几个数可以达到要求 题解: 考虑朴素的思想,对于每个i,我只需要删去最大的若 ...
- php简易分词
http://www.xunsearch.com/ 示例 http://www.xunsearch.com/scws/demo/v48.php