Hibernate關聯關係映射之多對多關聯關係,hibernate多對
本次仍然使用一個樣本的方式進行示範,學生與教師之間的關係就是一個典型的多對多關係,一個教師可以有多個學生,同樣一個學生也可以有多個教師。在資料庫中儲存需要一張學生表格儲存體學生資訊,一個教師表格儲存體教師資訊,為了表示他們之間的關係我們需要一個中間表來表示他們之間的聯絡。
例如,在教師表中有id,name兩個屬性,學生表中同樣有id,name兩個屬性。教師表中有兩條記錄分別是(1,董老師),(2,李老師);學生表中同樣有兩條(1,張三),(2,李四)。在中間表中有兩個欄位(teacherId,studentId),這兩個欄位構成一個聯合主鍵,同時這兩個欄位又是教師表和學生表的外鍵,老師和學生進行關聯的時候直接插入關聯的老師和學生的id在中間表內即可,例如在中間表中插入(1,1)表示董老師與張三進行關聯,插入(1,2)表示董老師與李四關聯。
下面我們看一下Teacher類和Student類
package entity;import java.util.HashSet;import java.util.Set;public class Teacher {private Long id;private String name;private Set<Student> students = new HashSet<Student>();public Long getId() {return id;}public void setId(Long 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;}}
package entity;import java.util.HashSet;import java.util.Set;public class Student {private Long id;private String name;private Set<Teacher> teachers = new HashSet<Teacher>();public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Set<Teacher> getTeachers() {return teachers;}public void setTeachers(Set<Teacher> teachers) {this.teachers = teachers;}}
在POJO類中仍然使用集合表示有多條記錄。
下面在看一個他們的映射設定檔
首先看Teacher.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping> <class name="entity.Teacher" table="Teacher" schema="MYHR"> <id name="id" type="long"> <column name="ID"/> <generator class="assigned" /> </id> <property name="name" type="string"> <column name="NAME" not-null="true" /> </property> <!-- students屬性,Set集合,表示本類與Student類的多對多關係 --> <set name="students" table="teacher_student" inverse="false"> <key column="teacherId" /> <many-to-many class="entity.Student" column="studentId"/> </set> </class></hibernate-mapping>
類中的Set類型的屬性在映射設定檔中仍然使用<set>標籤進行映射,在<set>標籤中使用<many-to-many>表示他們之間的關係是多對多。
然後看Student.hbm.xml
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping> <class name="entity.Student" table="Student" schema="MYHR"> <id name="id" type="long"> <column name="ID" /> <generator class="assigned" /> </id> <property name="name" type="string"> <column name="NAME" not-null="true" /> </property> <!-- teachers屬性, Set集合,表示本類與Teacher類的多對多關聯關係--> <!-- table:是實現多對多映射的中間表 --> <!-- key:集合外鍵(引用當前表主鍵的那個外鍵) --> <set name="teachers" table="teacher_student"> <key column="studentId" /> <many-to-many class="entity.Teacher" column="teacherId"/> </set> </class></hibernate-mapping>
這樣,教師和學生之間的多對多關聯映射就配置完了,下面看一下測試類別。這裡使用JUtil進行測試
package test;import static org.junit.Assert.*;import java.util.Iterator;import java.util.Set;import org.hibernate.Session;import org.hibernate.Transaction;import entity.Student;import entity.Teacher;import factory.HibernateSessionFactory;public class Test {private Session session = null;private Transaction tran = null;// 儲存物件@org.junit.Testpublic void save() {session = HibernateSessionFactory.getSession();tran = session.beginTransaction();try {Teacher teacher = new Teacher();teacher.setId(1L);teacher.setName("董老師");Teacher t2 = new Teacher();t2.setId(2l);t2.setName("李老師");Student s1 = new Student();s1.setId(1L);s1.setName("李四");Student s2 = new Student();s2.setId(2l);s2.setName("張三");teacher.getStudents().add(s1);teacher.getStudents().add(s2);t2.getStudents().add(s1);t2.getStudents().add(s2);s1.getTeachers().add(teacher);s1.getTeachers().add(t2);s2.getTeachers().add(teacher);s2.getTeachers().add(t2);session.save(teacher);session.save(t2);session.save(s1);session.save(s2);tran.commit();} catch (Exception e) {tran.rollback();}}// 擷取老師資訊@org.junit.Testpublic void GetTeacher() {session = HibernateSessionFactory.getSession();tran = session.beginTransaction();try {Teacher teacher = (Teacher) session.get(Teacher.class, 1l);Set<Student> set = teacher.getStudents();System.out.println(teacher.getName() + "的學生是:");Iterator<Student> it = set.iterator();while (it.hasNext()) {Student s = it.next();System.out.println(s.getName());}tran.commit();} catch (Exception e) {tran.rollback();}}// 解除關聯關係@org.junit.Testpublic void RemoveRelation() {session = HibernateSessionFactory.getSession();tran = session.beginTransaction();try {Student s = (Student) session.get(Student.class, 1l);Teacher teacher = (Teacher) session.get(Teacher.class, 1l);// 如果Teacher的inverse屬性為false可以解除,如果為true不可以解除teacher.getStudents().remove(s);tran.commit();} catch (Exception e) {tran.rollback();}}// 刪除關聯關係@org.junit.Testpublic void DeleteRelation() {session = HibernateSessionFactory.getSession();tran = session.beginTransaction();try {Teacher teacher = (Teacher) session.get(Teacher.class, 2l);// 當teacher的inverse屬性為false時,可以將教師資訊刪除,並且將中間表中相關記錄刪除// 當inverse屬性為true時將教師資訊刪除時拋出異常session.delete(teacher);tran.commit();} catch (Exception e) {tran.rollback();}}}
hibernate一對多映射時,單向關聯與雙向關聯有什不同,哪個好?
<one-to-many> 單向關聯就是只使用單方面來維護關係,雙向關聯就是雙方面都要維護關係, 要決定是使用單向的關聯還是雙向的關聯,要取決你的業務要求,如果單向聯絡能夠達到你所需要的業務要求,那肯定就是選擇單向的關聯(我的建議也是使用單向的關聯,使用雙向的關聯,關係複雜了,容易出現問題)。關聯的時候還涉及的就是控制權的問題,在<one-to-many>最好把控制權給與many的那方(控制權就是誰來維護他們之間的關係),
hibernate 多對多 利用聯合主鍵 映射一個複雜中間表的雙向多對多關聯
舉個例子:
多對多雙向關聯
關係舉例:老師<-->學生,老師需要知道自己教了哪些學生,學生也知道自己有哪些老師.
資料庫:中間表
Annotation:@ManyToMany
XML:<many-to-many>
多對多單向配置只需要在一端進行配置就可以了,雙向需要配置兩端.
關聯式模式(Teache多對多Student)
Teacher(id,name,students)多
Set<Student> students=new HashSet<Student>()
Student(id,name,teachers)多
Set<Teacher> teachers = new HashSet<Teacher>();
Annotation配置
在Teacher這一端的students上配置
//如果手動指定產生的中間表的表名和欄位名
@ManyToMany
@JoinTable(name="t_s",
joinColumns={@JoinColumn(name="teacher_id")},
inverseJoinColumns={@JoinColumn(name="student_id")}
)
在Student一端的teachers只需要配置
@ManyToMany(mappedBy="students")
XML配置方式:兩端配置一樣,注意表名和產生的中間表的欄位屬性名稱要一致
Teacher那一端配置
<set name="students" table="t_s">
<key column="teacher_id"/>
<many-to-many class="com.xxx.Student" column="student_id"/>
</set>
在Student那一端配置
<set name="teachers" table="t_s">
<key column="student_id"></key>
<many-to-many class="com.xxx.Teacher" column="teacher_id"/>
</set>
產生的表為
create table Student (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table Teacher (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table t_s (//產生的中間表
teacher_id integer not null,
student_id ......餘下全文>>