六、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 }

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 }

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" >

原文地址:https://www.cnblogs.com/qf123/p/10173799.html

时间: 2024-10-05 01:09:16

六、hibernate表与表之间的关系(多对多关系)的相关文章

【Java EE 学习第46天】【Hibernate学习第三天】【多对多关系映射】

一.多对多关系概述 以学生和课程之间的关系为例. 1.在多对多关系中涉及到的表有三张,两张实体表,一张专门用于维护关系的表. 2.多对多关系中两个实体类中应当分别添加对方的Set集合的属性,并提供set和get方法. 3.在配置映射文件的时候较一对多关系复杂. 二.映射文件 <set name="students" table="course_stu" cascade="save-update" inverse="true&quo

Hibernate框架之路(二)多对多多关系

1.配置实体类 package cn.pojo; import java.util.HashSet; import java.util.Set; public class User { /** * 用户表 */ private Integer user_id; private String user_name; private String user_pwd; private Set<Role> setRole = new HashSet<Role>(); public Integ

EF Core中如何设置数据库表自己与自己的多对多关系

本文的代码基于.NET Core 3.0和EF Core 3.0 有时候在数据库设计中,一个表自己会和自己是多对多关系. 在SQL Server数据库中,现在我们有Person表,代表一个人,建表语句如下: CREATE TABLE [dbo].[Person]( [PersonID] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](50) NULL, [Age] [int] NULL, CONSTRAINT [PK_Person] PRIMARY

Laravel5.1 模型 --多对多关系

多对多关系也是很常用的一种关系,比如一篇文章可以有多个标签,一个标签下也可以有多篇文章,这就是一个典型的多对多的关系. 1 实现多对多关系 多对多关系我们需要三张表,一张是文章另一张是标签,第三章表是它们的中间表 因为多对多关系需要抽离成两个一对多关系嘛. 1.1 文章结构 public function up() { Schema::create('articles', function (Blueprint $table) { $table->increments('id'); $table

六 Hibernate表关系及其配置

Hibernate的一对多关联映射 Hibernate的多对多关联映射 数据库表与表之间的关系:一对多,多对多,一对一 一对多:一个部门对应多个员工,一个员工只能属于一个部门.一个客户对应多个联系人,一个联系人只能属于一个客户 一对多建表:在多的一方创建外键. 多对多:一个学生可以选择多门课程,一门课程可以被多个学生选择.一个用户可以选择多个角色,一个角色可以被多个用户选择. 多对多建表:创建中间表.中间表至少有两个字段分别作为外键指向多对多双方的主键. 一对一(了解): 一般可以建成一张表.

MySQL数据库学习【第六篇】表与表之间的关系

表1 foreign key 表2 则表1的多条记录对应表2的一条记录,即多对一 利用foreign key的原理我们可以制作两张表的多对多,一对一关系 多对多: 表1的多条记录可以对应表2的一条记录 表2的多条记录也可以对应表1的一条记录 一对一: 表1的一条记录唯一对应表2的一条记录,反之亦然 分析时,我们先从按照上面的基本原理去套,然后再翻译成真实的意义,就很好理解了 1.先确立关系 2.找到多的一方,吧关联字段写在多的一方 一.多对一或者一对多(左边表的多条记录对应右边表的唯一一条记录)

六、数据库之 表与表之间的关系

表1 foreign key 表2 则表1的多条记录对应表2的一条记录,即多对一 利用foreign key的原理我们可以制作两张表的多对多,一对一关系 多对多: 表1的多条记录可以对应表2的一条记录 表2的多条记录也可以对应表1的一条记录 一对一: 表1的一条记录唯一对应表2的一条记录,反之亦然 分析时,我们先从按照上面的基本原理去套,然后再翻译成真实的意义,就很好理解了 1.先确立关系 2.找到多的一方,吧关联字段写在多的一方 一.多对一或者一对多(左边表的多条记录对应右边表的唯一一条记录)

第四天,表与表之间的关系,一对多,多对多,查询

※MySQL中的字符编码(注意,utf8中没有'-',跟Java中不一样)SHOW VARIABLES; //查看系统变量//查询字符编码相关的系统变量SHOW VARIABLES WHERE variable_name LIKE 'character%'; 解决MySQK的中文乱码:character_set_client,character_set_connection和character_set_results这三者必须一致(GBK,GB2312,UTF8这三者都可以,但若采用其中一种则3

MySQL---数据库从入门走上大神系列(四)-子查询、表与表之间的关系

本篇博客讲解(子查询)非相关子查询/相关子查询,一对一,一对多,多对一,多对的的关系! 准备: 首先我们创建一列sex.再为部分行设置好值0(女)或者1(男): delete from stud where age=26; 删除年龄为26的行. update stud set sex='1' where saddress like '湖南%'; 将地址中湖南开头的人的的sex修改为1. update stud set sex='0' where age>=30 and sex is null;