多对多也是分为:
- 单向多对多
- 双向多对多
案例说明:
一个学生可以上多个班级的课,一个班级也可以有多个学生
先来看看实体类
classes.java班级类
package entity;
import java.util.Set;
/**
* 这里还是用classes做测试,多对多,也就是一个学生可以在多个班上课,一个班可以有多个学生
* @author arkulo
*
*/
public class Classes {
private int id;
private String className;
private Set<Student> student;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public Set<Student> getStudent() {
return student;
}
public void setStudent(Set<Student> student) {
this.student = student;
}
}
Student.java学生类
package entity;
public class Student {
private int id;
private String name;
// private Classes classes;
// public Classes getClasses() {
// return classes;
// }
// public void setClasses(Classes classes) {
// this.classes = classes;
// }
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;
}
}
一、单向多对多
Classes.hbm.xml
<?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="entity">
<class name="Classes" dynamic-update="true" >
<id name="id">
<generator class="native"/>
</id>
<property name="className" />
<set name="student" table="_relation_classes_student">
<!-- 这里维护一张中间表,student_id关联student表,classes_id关联classes表 -->
<key column="classes_id"></key>
<many-to-many class="Student" column="student_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
这里要仔细注意中间表的写法,table确定表名称,key标签的column属性设置关联classes主键,manytomany标签column属性设置关联student表主键。现在对象之间的关联关系,是由classes维护的,student这边么有维护关系,请看下面的student的映射文件
student.hbm.xml
<?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="entity">
<class name="Student" dynamic-update="true">
<id name="id">
<generator class="native"/>
</id>
<property name="name" />
</class>
</hibernate-mapping>
单元测试:
package entity;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.classic.Session;
import junit.framework.TestCase;
import util.hibernateUtil;
/**
* 单向多对多关联
* 测试目的:
* 1. 测试添加
* 2. 测试查询
* 3. 测试删除
*
* @author arkulo
*
*/
public class testManyToMany extends TestCase {
// 新增,单向,是在classes端维护的关系
public void test1() {
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 先插入3条学生记录,然后插入班级记录,又插入三条关系表记录
Student st1 = new Student();
st1.setName("张三");
Student st2 = new Student();
st2.setName("李四");
Student st3 = new Student();
st3.setName("王五");
session.save(st1);
session.save(st2);
session.save(st3);
Set<Student> jihe = new HashSet();
jihe.add(st1);
jihe.add(st2);
jihe.add(st3);
Classes cl = new Classes();
cl.setClassName("一年级三班");
cl.setStudent(jihe);
session.save(cl);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
hibernateUtil.closeSession(session);
}
}
// 查询某个班的学生情况
public void test2()
{
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 这里先发出一个查询班级的sql语句,并打印。当需要用到与班级关联的学生的时候,
// 系统又发出了一条sql语句,将所有班级学生一起查出来
Classes cl = (Classes)session.get(Classes.class, 1);
System.out.println("班级名称:"+cl.getClassName());
Iterator<Student> it = cl.getStudent().iterator();
while(it.hasNext())
{
Student student = it.next();
System.out.println("学生姓名:"+student.getName());
}
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
hibernateUtil.closeSession(session);
}
}
// 删除班级是否会抛出异常?还是会一起删除学生
public void test3()
{
test1();
System.out.println("------------------------------------------");
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 这里先发出一个查询班级的sql语句,并打印。当需要用到与班级关联的学生的时候,
// 系统又发出了一条sql语句,将所有班级学生一起查出来
Classes cl = (Classes)session.get(Classes.class, 1);
System.out.println("班级名称:"+cl.getClassName());
Iterator<Student> it = cl.getStudent().iterator();
while(it.hasNext())
{
Student student = it.next();
System.out.println("学生姓名:"+student.getName());
}
// 这个时候缓存中已经存在班级和所有相关学生的对象缓存,这时候我们删除班级,看是否能一起删除学生数据
// 实际上,这个操作的sql语句如下:
// Hibernate: delete from _relation_classes_student where classes_id=?
// Hibernate: delete from Classes where id=?
// 先删除了关系表中的所有该班级的数据,然后删除了班级表中的数据记录
session.delete(cl);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
hibernateUtil.closeSession(session);
}
}
}
二、双向多对多
student.hbm.xml
<?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="entity">
<class name="Student" dynamic-update="true">
<id name="id">
<generator class="native"/>
</id>
<property name="name" />
<set name="classes">
<key column="student_id"></key>
<many-to-many class="Classes" column="classes_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
单元测试:
package entity;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.classic.Session;
import junit.framework.TestCase;
import util.hibernateUtil;
/**
* 双向多对多关联
* 测试目的:
* 一个课程班级对应多个学生,一个学生也可以报多个课程班级
* 1. 测试添加
* 2. 测试查询
* 3. 测试删除
*
* @author arkulo
*
*/
public class testManyToMany extends TestCase {
// 新增,双向,是在classes端维护的关系
public void test1() {
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 先插入3条学生记录,然后插入班级记录,又插入三条关系表记录
Student st1 = new Student();
st1.setName("张三");
Student st2 = new Student();
st2.setName("李四");
Student st3 = new Student();
st3.setName("王五");
session.save(st1);
session.save(st2);
session.save(st3);
Classes cl = new Classes();
cl.setClassName("音乐班");
Classes cl1 = new Classes();
cl1.setClassName("美术班");
Classes cl2 = new Classes();
cl2.setClassName("跆拳道班");
// 上音乐班的学生
Set<Student> jihe = new HashSet();
jihe.add(st1);
jihe.add(st2);
cl.setStudent(jihe);
// 上美术班的同学
Set<Student> jihe1 = new HashSet();
jihe1.add(st2);
jihe1.add(st3);
cl1.setStudent(jihe1);
// 上跆拳道班的学生
Set<Student> jihe2 = new HashSet();
jihe2.add(st1);
jihe2.add(st3);
cl2.setStudent(jihe2);
session.save(cl);
session.save(cl1);
session.save(cl2);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
hibernateUtil.closeSession(session);
}
}
// 查询某个班的学生情况
public void test2()
{
test1();
System.out.println("------------------------------");
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 这里先发出一个查询班级的sql语句,并打印。当需要用到与班级关联的学生的时候,
// 系统又发出了一条sql语句,将所有班级学生一起查出来
Classes cl = (Classes)session.get(Classes.class, 1);
System.out.println("班级名称:"+cl.getClassName());
Iterator<Student> it = cl.getStudent().iterator();
while(it.hasNext())
{
Student student = it.next();
System.out.println("学生姓名:"+student.getName());
}
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
hibernateUtil.closeSession(session);
}
}
// 删除班级是否会抛出异常?还是会一起删除学生
public void test3()
{
test1();
System.out.println("------------------------------------------");
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 这里先发出一个查询班级的sql语句,并打印。当需要用到与班级关联的学生的时候,
// 系统又发出了一条sql语句,将所有班级学生一起查出来
Classes cl = (Classes)session.get(Classes.class, 1);
System.out.println("班级名称:"+cl.getClassName());
Iterator<Student> it = cl.getStudent().iterator();
while(it.hasNext())
{
Student student = it.next();
System.out.println("学生姓名:"+student.getName());
}
// 这个时候缓存中已经存在班级和所有相关学生的对象缓存,这时候我们删除班级,看是否能一起删除学生数据
// 实际上,这个操作的sql语句如下:
// Hibernate: delete from _relation_classes_student where classes_id=?
// Hibernate: delete from Classes where id=?
// 先删除了关系表中的所有该班级的数据,然后删除了班级表中的数据记录
session.delete(cl);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
hibernateUtil.closeSession(session);
}
}
}