hibernate入门(八):多对多

4多对多关系映射:

典型实例:一个学生可以有多个老师,同样一个老师可以有多个学生,对此设计如下:

学生studnet表:

 

column

id

name

teachers

 

老师teacher表:

 

column

id

name

studnets

在利用学生查到他所有的老师,我们一般会设计中间表,来查找,中间表用来把学生和老师关联,通过此表进行学生和老师之间的交互查找。

中间表teacher_student:

 

column

teacher_id

studnet_id

 

            复合主键

在数据库操作中,作以下说明:如果通过老师查找学生,过程:先通过teacher表查找到id,再到teacher_student表中以teacher.id==teacher_student.teacher_id为查询条件来查找studnent_id , 查找到studnet_id后,再以teacher_student.stucent_id==student.id为查询条件来查找所有学生的信息。 同样通过学生查老师,也是类似的过程。

>>步骤一、创建实体类StudentTeacher

Student类内容如下:省略getXXX()setXXX()方法。

Java代码 复制代码
  1. package com.asm.hibernate.domain;   
  2. import java.util.Set;   
  3. public class Student {   
  4.     private int id;   
  5.     private String name;   
  6.     private Set<Teacher> teachers;       
  7. }  
package com.asm.hibernate.domain;
import java.util.Set;
public class Student {
	private int id;
	private String name;
	private Set<Teacher> teachers;	
}

 

Teacher类内容如下:省略getXXX()setXXX()方法。

Java代码 复制代码
  1. package com.asm.hibernate.domain;   
  2. import java.util.Set;   
  3. public class Teacher {   
  4.     private int id;   
  5.     private String name;   
  6.     private Set<Student> students;       
  7. }  
package com.asm.hibernate.domain;
import java.util.Set;
public class Teacher {
	private int id;
	private String name;
	private Set<Student> students;	
}

 

>>步骤二、为两个实体创建配置文件(省略了前面的xml文档声明内容):Student.hbm.xml内容如下:

Java代码 复制代码
  1. <hibernate-mapping    
  2.     package="com.asm.hibernate.domain">   
  3.     <class name="Student">   
  4.         <id name="id">   
  5.             <generator class="native"/>   
  6.         </id>   
  7.         <property name="name"></property>   
  8.         <set name="teachers" table="teacher_student">   
  9.             <key column="student_id" />   
  10.             <many-to-many class="Student" column="teacher_id"/>   
  11.         </set>   
  12.     </class>   
  13. </hibernate-mapping>  
<hibernate-mapping 
	package="com.asm.hibernate.domain">
	<class name="Student">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"></property>
		<set name="teachers" table="teacher_student">
			<key column="student_id" />
			<many-to-many class="Student" column="teacher_id"/>
		</set>
	</class>
</hibernate-mapping>

 

说明:这里重点说明最后的<set>配置:(1StudentSet类型的属性配置一个<set>元素,其实在前面的一对多中已经出现了<set>元素的配置,我们可以这样认为“凡是要为某个Set类型的属性进行映射配置,都可以用<set>元素来配置”。 <set>中的table属性为关联表的名称。 (2)它的子元素<key>中的column为关联表中以该映射文件所映射的表的主键为外键的字段名称. 3<many-to-many> coumn属性为关联表中以欲关联类对应表的主键为外键的字段名称。
Teacher.hbm.xml内容如下:

Java代码 复制代码
  1. <hibernate-mapping    
  2.     package="com.asm.hibernate.domain">   
  3.     <class name="Teacher">   
  4.         <id name="id">   
  5.             <generator class="native"/>   
  6.         </id>   
  7.         <property name="name"></property>   
  8.            
  9.         <set name="students" table="teacher_student">   
  10.             <key column="teacher_id" />   
  11.             <many-to-many class="Student" column="student_id"/>   
  12.         </set>   
  13.     </class>   
  14. </hibernate-mapping>  
<hibernate-mapping 
	package="com.asm.hibernate.domain">
	<class name="Teacher">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"></property>
		
		<set name="students" table="teacher_student">
			<key column="teacher_id" />
			<many-to-many class="Student" column="student_id"/>
		</set>
	</class>
</hibernate-mapping>

 

由于和Student.hbm.xml是类似的,这里不作说明,这样也就建立起了双向的多对多关联。

要注意他们所依赖的中间表为teacher_student,所以这里的<set>元素中的table属性和teacher映射文件相同,而特别要注意<key><many-to-many>column中属性值的设定。

>>步骤三、在主配置文件中关联实体配置文件:只需要增加如下内容:

<mapping resource="com/asm/hibernate/domain/Teacher.hbm.xml" />

<mapping resource="com/asm/hibernate/domain/Student.hbm.xml" />

>>步骤四、编写测试文件ManyToManyTest.java:省略导入的包。

Java代码 复制代码
  1. package com.asm.hibernate.test;   
  2. public class ManyToManyTest {   
  3.     public static void main(String[] args) {   
  4.         add();   
  5.     }   
  6.   
  7.     static void add() {   
  8.         Session s = null;   
  9.         Transaction tr = null;   
  10.         try {   
  11.             s = HibernateUtil.getSession();   
  12.             tr = s.beginTransaction();   
  13.   
  14.             Teacher t1 = new Teacher();   
  15.             t1.setName("t1Name");   
  16.   
  17.             Teacher t2 = new Teacher();   
  18.             t2.setName("t2Name");   
  19.   
  20.             Student s1 = new Student();   
  21.             s1.setName("s1Name");   
  22.   
  23.             Student s2 = new Student();   
  24.             s2.setName("s2Name");   
  25.   
  26.             // 再增加如下内容进行测试:   
  27.             Set<Teacher> ts = new HashSet<Teacher>();   
  28.             ts.add(t1);   
  29.             ts.add(t2);   
  30.             Set<Student> ss = new HashSet<Student>();   
  31.             ss.add(s1);   
  32.             ss.add(s2);   
  33.   
  34.             t1.setStudents(ss);   
  35.             t2.setStudents(ss);   
  36.   
  37.             // s1.setTeachers(ts);   
  38.             // s2.setTeachers(ts);   
  39.             // 增加内容完   
  40.             s.save(s1);   
  41.             s.save(s2);   
  42.             s.save(t1);   
  43.             s.save(t2);   
  44.             tr.commit();   
  45.   
  46.         } finally {   
  47.             if (s != null)   
  48.                 s.close();   
  49.         }   
  50.     }   
  51. }  
package com.asm.hibernate.test;
public class ManyToManyTest {
	public static void main(String[] args) {
		add();
	}

	static void add() {
		Session s = null;
		Transaction tr = null;
		try {
			s = HibernateUtil.getSession();
			tr = s.beginTransaction();

			Teacher t1 = new Teacher();
			t1.setName("t1Name");

			Teacher t2 = new Teacher();
			t2.setName("t2Name");

			Student s1 = new Student();
			s1.setName("s1Name");

			Student s2 = new Student();
			s2.setName("s2Name");

			// 再增加如下内容进行测试:
			Set<Teacher> ts = new HashSet<Teacher>();
			ts.add(t1);
			ts.add(t2);
			Set<Student> ss = new HashSet<Student>();
			ss.add(s1);
			ss.add(s2);

			t1.setStudents(ss);
			t2.setStudents(ss);

			// s1.setTeachers(ts);
			// s2.setTeachers(ts);
			// 增加内容完
			s.save(s1);
			s.save(s2);
			s.save(t1);
			s.save(t2);
			tr.commit();

		} finally {
			if (s != null)
				s.close();
		}
	}
}

 说明:注意以上注释掉的内容,如果去掉会出现异常。理解:加上增加的内容后再执行发现,在开启“数据库显示”功能后,发现控制台中新增加了四条插入语句,且是插入到中间表teacher_student中,在此处相当于告诉了每个学生所关联到的老师,而如果在mysql客户端执行“show create table teacher_student,观察它的表结构并结合“去掉注释的报错说明”,就容易理解到为什么不能有注释掉的内容。另需要说明的是“多对多”在操作和性能方面都不太理想,所以它使用较少,一般我们会选择转换成“一对多”的模型,而Hiberante的“多对多”实现,可能也是转换成两个“一对多”来实现.

你可能感兴趣的:(数据结构,Hibernate,xml,mysql)