多對多也是分為:
- 單向多對多
- 雙向多對多
案例說明:
一個學(xué)生可以上多個班級的課归粉,一個班級也可以有多個學(xué)生
先來看看實體類
classes.java班級類
package entity;
import java.util.Set;
/**
* 這里還是用classes做測試,多對多,也就是一個學(xué)生可以在多個班上課,一個班可以有多個學(xué)生
* @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學(xué)生類
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">
<!-- 這里維護(hù)一張中間表蜓陌,student_id關(guān)聯(lián)student表,classes_id關(guān)聯(lián)classes表 -->
<key column="classes_id"></key>
<many-to-many class="Student" column="student_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
這里要仔細(xì)注意中間表的寫法施蜜,table確定表名稱,key標(biāo)簽的column屬性設(shè)置關(guān)聯(lián)classes主鍵雌隅,manytomany標(biāo)簽column屬性設(shè)置關(guān)聯(lián)student表主鍵》現(xiàn)在對象之間的關(guān)聯(lián)關(guān)系,是由classes維護(hù)的恰起,student這邊么有維護(hù)關(guān)系修械,請看下面的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;
/**
* 單向多對多關(guān)聯(lián)
* 測試目的:
* 1. 測試添加
* 2. 測試查詢
* 3. 測試刪除
*
* @author arkulo
*
*/
public class testManyToMany extends TestCase {
// 新增,單向检盼,是在classes端維護(hù)的關(guān)系
public void test1() {
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 先插入3條學(xué)生記錄肯污,然后插入班級記錄,又插入三條關(guān)系表記錄
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);
}
}
// 查詢某個班的學(xué)生情況
public void test2()
{
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 這里先發(fā)出一個查詢班級的sql語句吨枉,并打印蹦渣。當(dāng)需要用到與班級關(guān)聯(lián)的學(xué)生的時候,
// 系統(tǒng)又發(fā)出了一條sql語句貌亭,將所有班級學(xué)生一起查出來
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("學(xué)生姓名:"+student.getName());
}
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
hibernateUtil.closeSession(session);
}
}
// 刪除班級是否會拋出異常柬唯?還是會一起刪除學(xué)生
public void test3()
{
test1();
System.out.println("------------------------------------------");
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 這里先發(fā)出一個查詢班級的sql語句,并打印圃庭。當(dāng)需要用到與班級關(guān)聯(lián)的學(xué)生的時候锄奢,
// 系統(tǒng)又發(fā)出了一條sql語句,將所有班級學(xué)生一起查出來
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("學(xué)生姓名:"+student.getName());
}
// 這個時候緩存中已經(jīng)存在班級和所有相關(guān)學(xué)生的對象緩存剧腻,這時候我們刪除班級斟薇,看是否能一起刪除學(xué)生數(shù)據(jù)
// 實際上,這個操作的sql語句如下:
// Hibernate: delete from _relation_classes_student where classes_id=?
// Hibernate: delete from Classes where id=?
// 先刪除了關(guān)系表中的所有該班級的數(shù)據(jù)恕酸,然后刪除了班級表中的數(shù)據(jù)記錄
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;
/**
* 雙向多對多關(guān)聯(lián)
* 測試目的:
* 一個課程班級對應(yīng)多個學(xué)生,一個學(xué)生也可以報多個課程班級
* 1. 測試添加
* 2. 測試查詢
* 3. 測試刪除
*
* @author arkulo
*
*/
public class testManyToMany extends TestCase {
// 新增蕊温,雙向袱箱,是在classes端維護(hù)的關(guān)系
public void test1() {
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 先插入3條學(xué)生記錄,然后插入班級記錄义矛,又插入三條關(guān)系表記錄
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("美術(shù)班");
Classes cl2 = new Classes();
cl2.setClassName("跆拳道班");
// 上音樂班的學(xué)生
Set<Student> jihe = new HashSet();
jihe.add(st1);
jihe.add(st2);
cl.setStudent(jihe);
// 上美術(shù)班的同學(xué)
Set<Student> jihe1 = new HashSet();
jihe1.add(st2);
jihe1.add(st3);
cl1.setStudent(jihe1);
// 上跆拳道班的學(xué)生
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);
}
}
// 查詢某個班的學(xué)生情況
public void test2()
{
test1();
System.out.println("------------------------------");
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 這里先發(fā)出一個查詢班級的sql語句发笔,并打印。當(dāng)需要用到與班級關(guān)聯(lián)的學(xué)生的時候凉翻,
// 系統(tǒng)又發(fā)出了一條sql語句了讨,將所有班級學(xué)生一起查出來
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("學(xué)生姓名:"+student.getName());
}
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
hibernateUtil.closeSession(session);
}
}
// 刪除班級是否會拋出異常?還是會一起刪除學(xué)生
public void test3()
{
test1();
System.out.println("------------------------------------------");
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 這里先發(fā)出一個查詢班級的sql語句,并打印前计。當(dāng)需要用到與班級關(guān)聯(lián)的學(xué)生的時候胞谭,
// 系統(tǒng)又發(fā)出了一條sql語句,將所有班級學(xué)生一起查出來
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("學(xué)生姓名:"+student.getName());
}
// 這個時候緩存中已經(jīng)存在班級和所有相關(guān)學(xué)生的對象緩存男杈,這時候我們刪除班級丈屹,看是否能一起刪除學(xué)生數(shù)據(jù)
// 實際上,這個操作的sql語句如下:
// Hibernate: delete from _relation_classes_student where classes_id=?
// Hibernate: delete from Classes where id=?
// 先刪除了關(guān)系表中的所有該班級的數(shù)據(jù)伶棒,然后刪除了班級表中的數(shù)據(jù)記錄
session.delete(cl);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
hibernateUtil.closeSession(session);
}
}
}