Hibernate关联关系中相对比较特殊的就是多对多关联,多对多关联与一对一关联和一对多关联不同,多对多关联需要另外一张映射表用于保存多对多映射信息。本例介绍多对多单向关联和双向关联。单向关联 :指具有关联关系的实体对象间的加载与访问关系是单向的。即,只有一个实体对象可以加载和访问对方,但对方是看不到另一方的。双向关联:双向关联是指具有关联关系的实体对象间的加载与访问关系是双向的。即,任何一方均可加载和访问另一方。
一、多对多单向关联
1、首先创建一个数据库,一条SQL语句搞定
create database many_to_many;
2、配置hibernate.cfg.xml
hibernate.cfg.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="hibernate.connection.url"> jdbc:mysql:///many_to_many </property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">123456</property> <property name="hibernate.dialect"> org.hibernate.dialect.MySQL5Dialect </property> <property name="hibernate.connection.provider_class"> org.hibernate.c3p0.internal.C3P0ConnectionProvider </property> <property name="hibernate.current_session_context_class"> thread </property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <mapping resource="com/beans/Course.hbm.xml" /> <mapping resource="com/beans/Student.hbm.xml" /> </session-factory> </hibernate-configuration>
3、创建实体类及其对应的映射文件
Course.java:
package com.beans;
public class Course {
private int cid;
private String cname;
public Course(String cname) {
// TODO Auto-generated constructor stub
this.cname = cname;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
}
Course.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 package="com.beans"> <!-- 完成类到表的映射,属性到字段的映射 --> <class name="Course"> <id name="cid"> <generator class="native" /> </id> <property name="cname"/> </class> </hibernate-mapping>
Student.java:
package com.beans;
import java.util.HashSet;
import java.util.Set;
public class Student {
private int sid;
private String sname;
private Set<Course> courses;
public Student(String sname) {
this();
this.sname = sname;
}
public Student() {
// TODO Auto-generated constructor stub
courses = new HashSet<Course>();
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
}
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 package="com.beans"> <!-- 完成类到表的映射,属性到字段的映射 --> <class name="Student"> <id name="sid"> <generator class="native" /> </id> <property name="sname"/> <set name="courses" cascade="save-update" table="middle" inverse="false"> <key column="studentId" /><!-- 指定当前类在中间表对应的外键 --> <many-to-many class="Course" column="courseId"/><!-- 指定关联类在中间表中对应的外键 --> </set> </class> </hibernate-mapping>
4、编写测试类
MyTest.java:
package com.test;
import org.hibernate.Session;
import org.junit.Test;
import com.beans.Course;
import com.beans.Student;
import com.utils.HbnUtils;
public class MyTest {
@Test
public void test01() {
Session session = HbnUtils.getSession();//HbnUtils为封装好的工具类
try {
session.beginTransaction();//开启事务
Course course1 = new Course("struts2");
Course course2 = new Course("hibernate5");
Course course3 = new Course("spring4");
Course course4 = new Course("mybatis");
Student student1 = new Student("Thanlon");
Student student2 = new Student("Tom");
student1.getCourses().add(course1);
student1.getCourses().add(course2);
student1.getCourses().add(course3);
student1.getCourses().add(course4);
student2.getCourses().add(course1);
student2.getCourses().add(course2);
student2.getCourses().add(course3);
session.save(student1);
session.save(student2);
session.getTransaction().commit();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
测试结果:
课程表:
学生表:
中间表:
二、多对多双向关联
1、接着上面的,可修改Course类如下。
Course.java:
package com.beans;
import java.util.HashSet;
import java.util.Set;
public class Course {
private int cid;
private String cname;
private Set<Student> students;
public Course(String cname) {
this();
this.cname = cname;
}
public Course() {
// TODO Auto-generated constructor stub
students = new HashSet<Student>();
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
}
2、映射文件可做如下修改
Course.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 package="com.beans"> <!-- 完成类到表的映射,属性到字段的映射 --> <class name="Course"> <id name="cid"> <generator class="native" /> </id> <property name="cname" /> <set name="students" cascade="save-update" table="middle" inverse="false"> <key column="courseId" /><!-- 指定当前类在中间表对应的外键 --> <many-to-many class="Student" column="studentId" /><!-- 指定关联类在中间表中对应的外键 --> </set> </class> </hibernate-mapping>