六、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 ...
随机推荐
- globalAlpha 示例
代码实例: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- python tkinter开始
tkinter是python自带的GUI库,所以用起来会比较简单 运行一个什么都没有的窗口 import tkinter window=tkinter.Tk()#窗口类定义 window.mainlo ...
- 【leetcode】722. Remove Comments
题目如下: Given a C++ program, remove comments from it. The program source is an array where source[i] i ...
- webpack CSS处理loader
loader概念: 首先来介绍一下loader,之前我们用webpack来处理我们写的js代码,并且webpack会自动处理js之间相关的依赖.但是,在开发中我们不仅仅有基本的js代码处理,我们也需要 ...
- Android USB驱动源码分析(-)
Android USB驱动中,上层应用协议里最重要的一个文件是android/kernel/drivers/usb/gadget/android.c.这个文件实现USB的上层应用协议. 首先包含了一些 ...
- CTF | bugku | 秋名山车神
''' @Modify Time @Author ------------ ------- 2019/8/31 19:55 laoalo ''' import requests from lxml i ...
- 【转】C#反编译工具
源地址:https://blog.csdn.net/kongwei521/article/details/54927689 源地址:https://www.cnblogs.com/JamesLi201 ...
- frida的js脚本处理正则的一个小坑
frida的server模式需要python支持,所以js脚本中的正则需要多一次转义 比如匹配"/proc/{数字pid}" server: paramPath.match(&qu ...
- vue搭建项目之设置axios
首先要下载axios: npm install axios -S 要注意的是,axios不支持Vue.use();这种方式,可以改写原型链. 第二步就是新建axios存放位置: 在项目中src中单独建 ...
- 【刷题笔记】686. Repeated String Match
题意 题目大意是,给两个字符串 A 和 B,问 B 是否能成为 A+A+A+...+A 的子字符串,如果能的话,那么最少需要多少个 A? 暴力解法 直接 A+A+...,到哪次 A 包含 B 了,就返 ...