多对多双向关联:数据库中有一张students表(字段 id和name),teachers表(字段id和name) 还有一张关联表 s_t(字段id 外键stu_id(参考students表的id)和tea_id(参考teachers表的id))
类图如下:Student中还存在一个teachers 的集合
Students.java
package com.org.model;
import java.util.Set;
public class Students {
private int id;
private String name;
private Set<Teacher> teachers;//多对多关系一般有一个中间表用于相关联,Hibernate面向对象,更注重于对象关系
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<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
}
Teacher.java
package com.org.model;
import java.util.Set;
public class Teacher {
private int id;
private String name;
private Set<Students> students;
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<Students> getStudents() {
return students;
}
public void setStudents(Set<Students> students) {
this.students = students;
}
}
Students.hbm.xml
<?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.org.model"> <class name="Students" table="students" > <id name="id"> <generator class="native"/> </id> <property name="name" not-null="true"/> <!-- set标签中的name用于指定映射的集合类型(即为Students类中多方对应的属性名 ) key标签中的column为s_t表中参照students表的外键--> <set name="teachers" cascade="save-update" inverse="true" table="s_t"> <key column="stu_id" not-null="true"></key> <!-- class表明set中放的是什么类型的集合,column指定s_t表中参照teacher表的外键 --> <many-to-many class="Teacher" column="tea_id"></many-to-many> </set> </class> </hibernate-mapping>
Teacher.hbm.xml
<?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.org.model"> <class name="Teacher" table="teachers" > <id name="id"> <generator class="native"/> </id> <property name="name" not-null="true"/> <!-- set标签中的name用于指定映射的集合类型(即为Teacher类中多方对应的属性名 ) key标签中的column为s_t表中参照teacher表的外键--> <set name="students" cascade="save-update" table="s_t"> <key column="tea_id" not-null="true"></key> <!-- class表明set中放的是什么类型的集合,column指定s_t表中参照students表的外键 --> <many-to-many class="Students" column="stu_id"></many-to-many> </set> </class> </hibernate-mapping>
hibernate.cfg.xml
<mapping resource="com/org/model/Students.hbm.xml" /> <mapping resource="com/org/model/Teacher.hbm.xml" />
测试类:
package com.org.model.test;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.org.model.Students;
import com.org.model.Teacher;
import com.org.util.HibernateUtil;
public class HibernateTest2 {
@Test
public void testSave1() {
Session session = null;
Transaction tx = null;
try {
// 拿到session
session = HibernateUtil.getSession();
// 开启事务
tx = session.beginTransaction();
// 给实体赋值
Set<Teacher> ts = new HashSet<Teacher>();
Teacher t1 = new Teacher();
t1.setName("XiangfGang1");
ts.add(t1);
Teacher t2 = new Teacher();
t2.setName("ZhengHui1");
ts.add(t2);
Teacher t3 = new Teacher();
t3.setName("WangJinFeng1");
ts.add(t3);
Set<Students> ss = new HashSet<Students>();
Students sd1 = new Students();
sd1.setName("ChengHai1");
ss.add(sd1);
Students sd2 = new Students();
sd2.setName("JiangKui1");
ss.add(sd2);
Students sd3 = new Students();
sd3.setName("YanJiaYang1");
ss.add(sd3);
t1.setStudents(ss);
t2.setStudents(ss);
t3.setStudents(ss);
session.save(t1);
session.save(t2);
session.save(t3);
// 告诉学生有哪些老师,与上面告诉老师有哪些学生任选一种即可
// sd1.setTeachers(ts);
// sd2.setTeachers(ts);
// sd3.setTeachers(ts);
// session.save(sd1);
// session.save(sd2);
// session.save(sd3);
// 提交事务
tx.commit();
} catch (Exception e) {
// 打印堆栈信息
e.printStackTrace();
// 事务回滚
if (tx != null) {
tx.rollback();
}
} finally {
HibernateUtil.closeSession(session);
}
}
}
结果:
Hibernate: insert into teachers (name) values (?)
Hibernate: insert into students (name) values (?)
Hibernate: insert into students (name) values (?)
Hibernate: insert into students (name) values (?)
Hibernate: insert into teachers (name) values (?)
Hibernate: insert into teachers (name) values (?)
Hibernate: insert into s_t (tea_id, stu_id) values (?, ?)
Hibernate: insert into s_t (tea_id, stu_id) values (?, ?)
Hibernate: insert into s_t (tea_id, stu_id) values (?, ?)
Hibernate: insert into s_t (tea_id, stu_id) values (?, ?)
Hibernate: insert into s_t (tea_id, stu_id) values (?, ?)
Hibernate: insert into s_t (tea_id, stu_id) values (?, ?)
Hibernate: insert into s_t (tea_id, stu_id) values (?, ?)
Hibernate: insert into s_t (tea_id, stu_id) values (?, ?)
Hibernate: insert into s_t (tea_id, stu_id) values (?, ?)
因为中间表的关系由Teacher端维护,所以插入Teacher的时候会插入关联关系。只能一段来维护关系,不能两端同时维护关系,这样会导致在中间表出现重复插入的现象。