`

九 多对多关系 学生<--->老师的关系

 
阅读更多
九 多对多关系 学生<--->老师的关系
多对多关系 学生<--->老师的关系 一个学生可以有多个老师 一个老师可以有多个学生
在多对多的关系的表 在操作和性能方面都不太理想,所以多对多的映射使用较少,
实际使用中最好转换成一对多的对象模型;Hibernate会为我们创建中间关联表,转换成两个一对多。

具体操作是这样的 比如说我们建一个老师表 teacher 和一个学生表 student 怎么让这两个表连成有关系的表呢 
可以这样去设计 设计一个中间表teacher_student 中间表里仅仅存的是teacher的id 和student的id 并且建一个主键,
主键是这两个键的组合键 我们只要把这两个id作为外键的形式存放在这个中间表中便可以了 然后由这个中间表去
跟teacher和student表建立关系便可以,这个关系就是一对多的关系 一个中间表跟两个表建立关系

那现在我们开始吧
先设计模型 

Teacher类 
package hibernate.many;

import java.util.Set;

public class Teacher {
  private int id;
  private String name;
  private Set<Student> students;
public int getId() {
	return id;
}
public void setId(int id) {
	this.id = id;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public Set<Student> getStudents() {
	return students;
}
public void setStudents(Set<Student> students) {
	this.students = students;
}
}


映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping 
	package="hibernate.many">

	<class name="Teacher">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		
		<set name="students" table="teacher_student">
		<key column="teacher_id"/>
		  <many-to-many  class="Student" column="student_id"/>
		</set>
	</class>
	
</hibernate-mapping>

分析:比如说我们要根据teacher去查找student的信息 我们该怎样去查呢 
首先我们查找到teacher的信息 我们根据这个teacher的id 去查teacher_student中间表的数据
这样就可以查出student_id 这个student_id就是student的id 现在我们查学生就不难查出来了吧
看上面的配置 这是个实体类的映射文件 注意看set部分 set存的是什么 就是这个Teacher实体存的属性
属性名是什么 是students 看students其实就是这个实体的属性 上面class节点不是已经有默认的对应的表
吗?默认的对应的表也就是这个实体的表对应的表是小写的teacher名的表 那这里这个table是干嘛的呢 
这个啊 就是指定的中间表啊 这个中间表teacher_student在这里是一个条件存在的 说的是如果通过查老师
就可以查中间表了,查询的条件是什么呢?看key节点了吧 这个节点就是查询的条件,指的是这个中间表引用
当前Teacher的id作为外键存放到中间表的 好,现在就查中间表了,现在进一步分析 那many-to-many节点是什么意思呢
这里指定的是,告诉hibernate现在要查这个中间表的下一个表的条件 class是告诉现在还可以查的是什么表 
class="Student" 哈哈,原来啊,这个set存放的Student这个实体啊 那要查这个Student实体的数据,该怎么查呢 
现在不是又告诉你条件了吗?看column告诉你条件是student_id就可以查Student的数据,指定这个column就是告诉
hibernate这个中间表的字段student_id是引用Student实体的id作为外键而存放的 到这步,数据不全都出来了吗 
小结:发现这个set指定的都是teacher_student的字段 指定的两个列都是作为查询条件而存在的 现在理解了吧!并且在
注意哦!这里指定的一切列名都不在设计的实体哦 





Student类

package hibernate.many;

import java.util.Set;

public class Student {
   private int id;
   private String name;
   private Set<Teacher> teacher;
   
public int getId() {
	return id;
}
public void setId(int id) {
	this.id = id;
}

public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}

public Set<Teacher> getTeacher() {
	return teacher;
}
public void setTeacher(Set<Teacher> teacher) {
	this.teacher = teacher;
}
}

映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping 
	package="hibernate.many">

	<class name="Student">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		
		<set name="teacher" table="teacher_student">
		<key column="student_id"/>
		  <many-to-many class="Teacher" column="teacher_id"/>
		</set>
	</class>
	
</hibernate-mapping>

分析,这里可以按照上面的那种分析原理便可



测试
package hibernate.test;


import java.util.HashSet;
import java.util.Set;

import hibernate.many.Student;
import hibernate.many.Teacher;
import hibernate.util.HibernateUtil;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.jboss.util.HashCode;

public class ManyToMany {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		add();
		query(1);
	}
	  static void add(){
		   Session session=null;
		   Transaction tx=null;
		   try{
			   session=HibernateUtil.getSession();
			   tx=session.beginTransaction();
			   
			   Set<Teacher> t=new HashSet<Teacher>();
			   Teacher t1=new Teacher();
			   t1.setName("曾笑先老师");
			   t.add(t1);
			   
			   Teacher t2=new Teacher();
			   t2.setName("莫如非老师");
			   t.add(t2);
			   
			   Set<Student> s=new HashSet<Student>();
			   Student s1=new Student();
			   s1.setName("潘长江学生");
			   s.add(s1);
			   
			   Student s2=new Student();
			   s2.setName("如烟学生");
	           s.add(s2);
	           
	           t1.setStudents(s);
	           t2.setStudents(s);
	           
			  // s1.setTeacher(t);
			  // s2.setTeacher(t);
	
			   
			   session.save(t1);
			   session.save(t2);
			   session.save(s1);
			   session.save(s2);
			   tx.commit();
			
		   }finally{
			   if(session!=null) session.close();
		   }
	   }
	   
	   static void query(int id){
		   Session session=null; 
		   try{
			   session=HibernateUtil.getSession();
			   Teacher t=(Teacher)session.get(Teacher.class, 1);
			   System.out.println(t.getName()+"-------->"+t.getStudents().size());
		   }finally{
			   if(session!=null) session.close();
		   }
	   }
}



分析:s1.setTeacher(t);s2.setTeacher(t); t1.setStudents(s); t2.setStudents(s);为什么不能都执行呢?
这跟中建表teacher_student的表结构有关 表结构的主键是以Teacher的id和Student的id组合键作为id的,
如果都执行就会出现主键重复异常的信息 现在来看ddl语句  
CREATE TABLE `teacher_student` (
  `student_id` int(11) NOT NULL,
  `teacher_id` int(11) NOT NULL,
  PRIMARY KEY  (`teacher_id`,`student_id`),
  KEY `FK2E2EF2DE28DF55E7` (`teacher_id`),
  KEY `FK2E2EF2DE18440B47` (`student_id`),
  CONSTRAINT `FK2E2EF2DE18440B47` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`),
  CONSTRAINT `FK2E2EF2DE28DF55E7` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

现在就知道了吧 当你执行完s1.setTeacher(t);s2.setTeacher(t);后,如果再次t1.setStudents(s); t2.setStudents(s);
执行,hibernate接受的teacher的id和Student的id其实跟前两句是一样的,组合成的主键也是一样的 ,这不就违反主键约束了吗


总结:这种多对多或者一对多在程序的性能上是比较低的,在使用的时候,要特别注意,我们可以去使用单向的一对多或者多对多
多对多查询一条数据 往往查询的是两张表,这在应用中其实是比较少的,如果数据量特别庞大,会出现很严重的问题
尽量要用单向的多对多或者一对多,单向的一对一,只需在映射文件中配置一方即可,配置哪一方只需考虑其对应的一方的数据量

完毕 end!

 

分享到:
评论

相关推荐

    Web前端开发技术课程大作业:基于HTML+CSS+JavaScript实现校园主题-萍乡田家炳中学校网站(1页)

    - **页面数量**:该作业要求包含多个页面,通过相互之间的超链接实现导航,有助于训练学生在多个页面之间建立逻辑关系的能力。 - **交互性**:要求具备一定的JS特效,例如图片轮播等,这些动态效果能够增加用户的...

    Hibernate继承映射的第一种策略:每个类对应一张表

    -- 学生特有的属性 --&gt; &lt;/subclass&gt; &lt;/hibernate-mapping&gt; ``` 3. 子类`Teacher`的映射: ```xml &lt;hibernate-mapping&gt; &lt;subclass name="com.example.Teacher" extends="com.example.Person" table="TEACHER"&gt; ...

    简单学生成绩管理系统

    &lt;caption&gt;学生成绩管理&lt;/caption&gt; &lt;!-- 查询按钮与表单 --&gt; &lt;form method="post" action=""&gt; &lt;input type="text" name="query" placeholder="请输入查询条件"&gt; &lt;input type="submit" value="查询"&gt; &lt;/form&gt; ...

    8.pdf

    &lt;student_shankar&gt; &lt;has_take_tuples&gt; &lt;take_tuple_id1&gt;, &lt;take_tuple_id2&gt; . &lt;student_shankar&gt; &lt;has_setuples&gt; &lt;setuple_id1&gt;, &lt;setuple_id2&gt; . ``` 8.1 RDF图表示:与RDF三元组类似,但以图形化方式展示这些关系...

    mybatis一对多多对一

    在MyBatis中,我们使用`&lt;association&gt;`标签来映射多对一关系,如下所示: ```xml &lt;resultMap id="courseMap" type="Course"&gt; &lt;!-- 其他属性映射... --&gt; &lt;association property="teacher" javaType="Teacher"&gt; ...

    10 映射-- 多对多(老师与学生)

    在我们的例子中,一个老师可以教多个学生,同时一个学生也可以被多个老师教授,这种关系就体现了多对多的特性。在数据库层面,通常通过中间表来实现这种关系,它包含了两个实体的主键,作为联合主键。 在Hibernate...

    java XML的使用方式 小白文.md

    &lt;name&gt;&lt;age&gt;小泽马老师&lt;/name&gt; 18&lt;/age&gt; &lt;/person&gt; ``` - 一个XML文档只能有一个根标记。例如下面的代码是正确的: ``` &lt;persons&gt; &lt;person&gt; &lt;name&gt;小泽马老师&lt;/name&gt; &lt;age&gt;18&lt;/age&gt; &lt;/person&gt; &lt;/persons...

    ibatis多对多关系(详细)

    在本例中,我们将使用学生(Student)和教师(Teacher)之间的多对多关系作为示例。一个学生可以有多个教师,而一个教师也可以有多个学生。 数据库设计 首先,我们需要设计数据库表来存储学生和教师之间的多对多...

    Hibernate继承映射二:每个子类一张表

    -- 学生特有的属性 --&gt; &lt;/subclass&gt; &lt;subclass name="com.example.Teacher" table="TEACHER"&gt; &lt;discriminator value="T"/&gt; &lt;!-- 教师特有的属性 --&gt; &lt;/subclass&gt; &lt;/hibernate-mapping&gt; ``` 这里,`abstract=...

    三年级排序专项练习.docx

    正确的顺序是:陈景润敬重老师 -&gt; 老师批评作业 -&gt; 第二天作业端正 -&gt; 数学成就 -&gt; 给老师写信 -&gt; 认为尊敬老师是基本礼貌 -&gt; 登门拜访老师。这个故事强调了陈景润对老师的敬重和他对学术严谨的态度。 3. 肖邦的...

    Hibernate一对多教学

    1. XML映射文件:在Hibernate的映射文件中,使用`&lt;set&gt;`或`&lt;list&gt;`标签来表示一对多关系。`&lt;one-to-many&gt;`标签用于定义多的一方如何关联到一的一方。比如,对于老师和学生的关系,学生实体(Student)会有一个`&lt;set&gt;...

    课程及成绩管理信息系统

    - **教务人员模块**:教务人员可对学生、教师和课程的基本信息进行录入、修改和查询。 - **教师选课模块**:教师可以录入自己将要讲授的课程。 - **学生选课模块**:学生可以从已开设的课程列表中进行选课。 - **...

    MyBatis高级映射(一对多查询)

    对于一对多关系,通常使用`&lt;association&gt;`或`&lt;collection&gt;`标签来定义。例如,假设我们有一个`Department`类和一个`Employee`类,一个部门可以包含多个员工: ```xml &lt;!-- Department 映射 --&gt; &lt;mapper ...

    IBatis: Discriminator Column Example – Inheritance Mapping(Ibatis中的继承映射)

    在iBATIS的映射文件中,我们需要定义一个`&lt;resultMap&gt;`来处理这种继承关系,并使用`&lt;discriminator&gt;`元素来根据`discriminator`列的值决定实例化哪个子类。 `&lt;resultMap&gt;`配置如下: ```xml &lt;resultMap id=...

    hibernate的联合主键怎么设置

    例如,在学生(Student)和教师(Teacher)的多对多关系中,使用一个中间表(TeacherStudent)来存储关联。如果 Student 的 `inverse="true"`,那么添加一个新的 Student 时,Hibernate 不会在 TeacherStudent 表中...

    毕业论文161SSM 成绩管理系统.doc

    学生信息表 &lt;-----&gt; 教师信息表 | | | | 成绩信息表 &lt;-----&gt; 课程信息表 数据字典 以下是本系统的数据字典: * 学生信息表: + 学号(主键) + 姓名 + 密码 * 教师信息表: + 工号(主键) + 姓名 + 密码 *...

    java 一对多的操作

    例如,一个学生可以有多个课程,一个老师可以教多个班级等。这种关系在Java中通常通过ORM(对象关系映射)框架如Hibernate来实现。以下是对这个主题的详细阐述: 首先,我们需要理解一对多关系的基础概念。在数据库...

    hibernate实现多对一得单项关联

    1. XML映射方式:在Hibernate的XML映射文件中,我们可以使用`&lt;many-to-one&gt;`标签来表示多对一的关联。例如,如果有一个`Student`类和一个`Teacher`类,`Student`可以有多位老师,而`Teacher`只对应一个班级,那么在`...

    VBaccess学生信息管理系统

    &lt;br&gt;&lt;br&gt;目 录&lt;br&gt;摘要 1&lt;br&gt;ABSTRACT 2&lt;br&gt;前言 1&lt;br&gt;第一章 系统概述 2&lt;br&gt;1.1 系统介绍 2&lt;br&gt;1.2 课题目的及意义 2&lt;br&gt;1.3 主要设计功能 3&lt;br&gt;第二章 开发方法的选择 4&lt;br&gt;2.1 开发工具的选择 4&lt;br&gt;2.2 WINDOWS下...

Global site tag (gtag.js) - Google Analytics