多对多双向关联:数据库中有一张students表(字段 id和name),teachers表(字段id和name) 还有一张关联表 s_t(字段id 外键stu_id(参考students表的id)和tea_id(参考teachers表的id))
类图如下:Student中还存在一个teachers 的集合
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的时候会插入关联关系。只能一段来维护关系,不能两端同时维护关系,这样会导致在中间表出现重复插入的现象。