J2EE系列之Hibernate4学习笔记(十四)--多对多映射

本文通过学生课程的例子深入探讨Hibernate4中的多对多映射,包括单向和双向映射的实现。首先介绍了单向多对多映射,展示了如何查询学生的所有课程,但无法查询课程对应的学生。接着,讲解了双向多对多映射,允许从学生和课程两个角度查看关联关系。通过映射文件配置和测试函数,详细解析了多对多映射的配置和使用。
摘要由CSDN通过智能技术生成

以学生课程这个多对多映射为例,每个学生可以选多门课程,而每门课程又可以被多个学生选择。多对多映射可以分为两种:单向的多对多和双向的多对多

一、单向的多对多映射:这里以学生为主,可以查询每个学生选修的多门课程,但是不能查询选修某个课程的学生

1.新建学生类Student:

package com.test.model;

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

public class Student {

	private int id;
	private String name;
	
	private Set<Course> courses = new HashSet<Course>();

	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<Course> getCourses() {
		return courses;
	}

	public void setCourses(Set<Course> courses) {
		this.courses = courses;
	}
	
	
}
这个类中包括id,学生名称,选修的课程三个属性。

2.新建课程类Course:

package com.test.model;

public class Course {

	private int id;
	private String name;
	
	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;
	}
	
	
}

课程类中有id和课程名称两个属性。


3.编写Student的映射文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.test.model">

	<class name="Student" table="t_student">
		<id name="id" column="studentId">
			<generator class="native"></generator>
		</id>
		<property name="name" column="studentName"></property>
		
		<set name="courses" table="student_courses" cascade="save-update">
			<key column="student_id"></key>
			<many-to-many class="com.test.model.Course" column="course_id"></many-to-many>
		</set>
	</class>

</hibernate-mapping>

这里重点说一下<set>标签,使用<set>标签定义学生类中的集合元素courses,把这个元素重新成一张新的数据表student_courses,student_courses这个数据表的外键student_id映射t_student表的主键,这个表的外键course_id映射Course类数据表的主键。cascade属性值为save-update表明当保存t_student表中的数据时级联保存student_courses中的数据。

4.编写Course类的映射文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.test.model">

	<class name="Course" table="t_course">
		<id name="id" column="courseId">
			<generator class="native"></generator>
		</id>
		<property name="name" column="courseName"></property>
		
	</class>

</hibernate-mapping>

这个表没啥好说的。


5.把这两个映射文件添加到配置文件中。写测试函数:

@Test
	public void testSave1(){
		
		Course course1 = new Course();
		course1.setName("语文");
		
		Course course2 = new Course();
		course2.setName("数学");
		
		Student student1 = new Student();
		student1.setName("张三");
		student1.getCourses().add(course1);
		student1.getCourses().add(course2);
		
		Student student2 = new Student();
		student2.setName("李四");
		student2.getCourses().add(course1);
		student2.getCourses().add(course2);
		
		session.save(student1);
		session.save(student2);
	}
	
	@Test
	public void testLoad1(){
		
		Student student = (Student)session.get(Student.class, 1);
		Set<Course> courses = (Set<Course>) student.getCourses();
		Iterator it = courses.iterator();
		while(it.hasNext()){
			Course c = (Course) it.next();
			System.out.println(c.getName());
		}
	}

运行testSave1方法,生成的数据库表结构为:

生成的表中的数据为:

                       


运行testLoad1方法,查询学号为1的学生选择的课程:


2.双向多对多映射

1.新建学生类Student2:

package com.test.model;

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

public class Student2 {

	private int id;
	private String name;
	
	private Set<Course2> courses = new HashSet<Course2>();

	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<Course2> getCourses() {
		return courses;
	}

	public void setCourses(Set<Course2> courses) {
		this.courses = courses;
	}

	
	
}

2.新建课程类Course2:

package com.test.model;

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

public class Course2 {

	private int id;
	private String name;
	private Set<Student2> students = new HashSet<Student2>();
	
	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<Student2> getStudents() {
		return students;
	}
	public void setStudents(Set<Student2> students) {
		this.students = students;
	}
	
	
	
}

这里为了实现双向查询,课程类中添加了学生类的集合属性。

3.编写学生类映射文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.test.model">

	<class name="Student2" table="t_student2">
		<id name="id" column="studentId">
			<generator class="native"></generator>
		</id>
		<property name="name" column="studentName"></property>
		
		<set name="courses" table="student_courses2" cascade="save-update">
			<key column="student_id"></key>
			<many-to-many class="com.test.model.Course2" column="course_id"></many-to-many>
		</set>
	</class>

</hibernate-mapping>

4.编写课程类映射文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.test.model">

	<class name="Course2" table="t_course2">
		<id name="id" column="courseId">
			<generator class="native"></generator>
		</id>
		<property name="name" column="courseName"></property>
		
		<set name="students" table="student_courses2" inverse="true">
			<key column="course_id"></key>
			<many-to-many class="com.test.model.Student2" column="student_id"></many-to-many>
		</set>
	</class>

</hibernate-mapping>

这里<set>标签中设置了inverse的值为true,这表示又学生类一端来维护表关系。


5.以上两个映射文件添加到配置文件中,写测试方法:

@Test
	public void testSave2(){
		
		Course2 course1 = new Course2();
		course1.setName("语文");
		
		Course2 course2 = new Course2();
		course2.setName("数学");
		
		Student2 student1 = new Student2();
		student1.setName("张三");
		student1.getCourses().add(course1);
		student1.getCourses().add(course2);
		
		Student2 student2 = new Student2();
		student2.setName("李四");
		student2.getCourses().add(course1);
		student2.getCourses().add(course2);
		
		session.save(student1);
		session.save(student2);
	}
	
	@Test
	public void testLoad2(){
		
		Course2 course = (Course2) session.get(Course2.class, 1);
		Set<Student2> students = (Set<Student2>)course.getStudents();
		Iterator it = students.iterator();
		
		while(it.hasNext()){
			Student2 s = (Student2) it.next();
			System.out.println(s.getName());
		}
	}

运行testSave2方法,生成的表结构为:

生成的数据为:

                    

运行testLoad2方法,查询选择了语文课程的学生:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值