多对多
什么情况下会出现多对多呢?比如学生选课就会出现多对多的情况,那么我们在数据库层面是怎么解决这种问题的呢,通常会有三张表,
学生表
ID 学生姓名
1 张三
2 李四
3 王五
课程表
ID 课目名
1 Java
2 SQL
3 JavaScript
学生_课程表
ID 学生ID 课目ID
1 2 1
2 2 3
3 3 2
4 3 1
5 1 1
6 1 2
7 1 3
那么从学生_课程的表中我们只需要知道学生ID,或者科目ID,便可以清楚的查询出每个学生选修的科目,以及指定的科目被哪些学生选修了.
那么这种情况反映到Hibernate中呢,是怎么对应呢?
在Hibernate中,多对多,其实是多个一对多.
但是在定位哪是多,哪是一的问题上,你需要站在学生或者科目的角度来考虑,
比如
学生角度,学生张三现在修了哪几门科目,那么学生张三是一, 科目是多,所以学生类中应该持有一个科目集合
科目角度,Java这门课被哪几个学生选修过,那么这时科目应该是一,学生是多,那么这时,科目类中就应该持有一个学生集合
但是所持有的科目集合或学生集合又不是直接对应的集合,而是所谓中间表(学生_课程表)对应的类集合.
请看下面的代码实现:
Model层:
Student:
public class Student {
private String id;
private String stuName;
private Set<StuSub> stuSubs = new HashSet<StuSub>();
public Student() {
}
public Student(String stuName) {
super();
this.stuName = stuName;
}
public Student(String stuName, Set<StuSub> stuSubs) {
this.stuName = stuName;
this.stuSubs = stuSubs;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getStuName() {
return this.stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public Set<StuSub> getStuSubs() {
return this.stuSubs;
}
public void setStuSubs(Set<StuSub> stuSubs) {
this.stuSubs = stuSubs;
}
}
Subject:
public class Subject {
private String id;
private String subName;
private Set<StuSub> stuSubs = new HashSet<StuSub>();
public Subject() {
}
public Subject(String subName) {
super();
this.subName = subName;
}
public Subject(String subName, Set<StuSub> stuSubs) {
this.subName = subName;
this.stuSubs = stuSubs;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getSubName() {
return this.subName;
}
public void setSubName(String subName) {
this.subName = subName;
}
public Set<StuSub> getStuSubs() {
return this.stuSubs;
}
public void setStuSubs(Set<StuSub> stuSubs) {
this.stuSubs = stuSubs;
}
}
StuSub:
public class StuSub {
private String id;
private Student student;
private Subject subject;
public StuSub() {
}
public StuSub(Student student, Subject subject) {
this.subject = subject;
this.student = student;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public Subject getSubject() {
return this.subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
public Student getStudent() {
return this.student;
}
public void setStudent(Student student) {
this.student = student;
}
}
映射文件:
Student.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="chapter4.model.Student" table="student">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="stuName" type="java.lang.String">
<column name="stuName" length="20" />
</property>
<set name="stuSubs">
<key>
<column name="stu_id" length="32" />
</key>
<one-to-many class="chapter4.model.StuSub" />
</set>
</class>
</hibernate-mapping>
Subject.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="chapter4.model.Subject" table="subject">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="subName" type="java.lang.String">
<column name="subName" length="20" />
</property>
<set name="stuSubs">
<key>
<column name="sub_id" length="32" />
</key>
<one-to-many class="chapter4.model.StuSub" />
</set>
</class>
</hibernate-mapping>
StuSub.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="chapter4.model.StuSub" table="stu_sub">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex"/>
</id>
<many-to-one name="subject" class="chapter4.model.Subject">
<column name="sub_id" length="32" />
</many-to-one>
<many-to-one name="student" class="chapter4.model.Student">
<column name="stu_id" length="32" />
</many-to-one>
</class>
</hibernate-mapping>
Dao层:
StudentDao:
public class StudentDao {
public void create(Student student) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.save(student);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public Student findById(Serializable id) throws Exception {
Session session = null;
Student student = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
student = (Student) session.get(Student.class, id);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return student;
}
}
SubjectDao:
public class SubjectDao {
public void create(Subject subject) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.save(subject);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public Subject findById(Serializable id) throws Exception {
Session session = null;
Subject subject = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
subject = (Subject) session.get(Subject.class, id);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return subject;
}
}
StuSubDao:
public class StuSubDao {
public void create(StuSub stuSub) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.save(stuSub);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public StuSub findById(Serializable id) throws Exception {
Session session = null;
StuSub stuSub = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
stuSub = (StuSub) session.get(StuSub.class, id);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return stuSub;
}
}
测试文件:
Test:
public class Test {
public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
StuSubDao stuSubDao = new StuSubDao();
SubjectDao subjectDao = new SubjectDao();
//创建两个学生
Student student1 = new Student("张三");
Student student2 = new Student("李四");
//创建三门科目
Subject subject1 = new Subject("java");
Subject subject2 = new Subject("sql");
Subject subject3 = new Subject("javaScript");
//张三报了三门课
StuSub stuSub1 = new StuSub(student1, subject1);
StuSub stuSub2 = new StuSub(student1, subject2);
StuSub stuSub3 = new StuSub(student1, subject3);
//李四报了二门课
StuSub stuSub4 = new StuSub(student2, subject1);
StuSub stuSub5 = new StuSub(student2, subject2);
//保存学生入库
studentDao.create(student1);
studentDao.create(student2);
//保存科目入库
subjectDao.create(subject1);
subjectDao.create(subject2);
subjectDao.create(subject3);
//保存张三选修的科目入库
stuSubDao.create(stuSub1);
stuSubDao.create(stuSub2);
stuSubDao.create(stuSub3);
//保存李四选修的科目入库
stuSubDao.create(stuSub4);
stuSubDao.create(stuSub5);
//知道张三的ID,查找张三选修了哪几门科目
Student student = studentDao.findById("40285c8127aa1e9d0127aa1e9ed50001");
Set<StuSub> set1 = student.getStuSubs();
for(StuSub stuSub : set1){
System.out.println(stuSub.getSubject().getSubName());
}
//知道Java科目的ID,查找有哪些人修过Java科目
Subject subject = subjectDao.findById("40285c8127aa1e9d0127aa1e9fbf0005");
Set<StuSub> set2 = subject.getStuSubs();
for(StuSub stuSub : set2){
System.out.println(stuSub.getStudent().getStuName());
}
}
}
什么情况下会出现多对多呢?比如学生选课就会出现多对多的情况,那么我们在数据库层面是怎么解决这种问题的呢,通常会有三张表,
学生表
ID 学生姓名
1 张三
2 李四
3 王五
课程表
ID 课目名
1 Java
2 SQL
3 JavaScript
学生_课程表
ID 学生ID 课目ID
1 2 1
2 2 3
3 3 2
4 3 1
5 1 1
6 1 2
7 1 3
那么从学生_课程的表中我们只需要知道学生ID,或者科目ID,便可以清楚的查询出每个学生选修的科目,以及指定的科目被哪些学生选修了.
那么这种情况反映到Hibernate中呢,是怎么对应呢?
在Hibernate中,多对多,其实是多个一对多.
但是在定位哪是多,哪是一的问题上,你需要站在学生或者科目的角度来考虑,
比如
学生角度,学生张三现在修了哪几门科目,那么学生张三是一, 科目是多,所以学生类中应该持有一个科目集合
科目角度,Java这门课被哪几个学生选修过,那么这时科目应该是一,学生是多,那么这时,科目类中就应该持有一个学生集合
但是所持有的科目集合或学生集合又不是直接对应的集合,而是所谓中间表(学生_课程表)对应的类集合.
请看下面的代码实现:
Model层:
Student:
public class Student {
private String id;
private String stuName;
private Set<StuSub> stuSubs = new HashSet<StuSub>();
public Student() {
}
public Student(String stuName) {
super();
this.stuName = stuName;
}
public Student(String stuName, Set<StuSub> stuSubs) {
this.stuName = stuName;
this.stuSubs = stuSubs;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getStuName() {
return this.stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public Set<StuSub> getStuSubs() {
return this.stuSubs;
}
public void setStuSubs(Set<StuSub> stuSubs) {
this.stuSubs = stuSubs;
}
}
Subject:
public class Subject {
private String id;
private String subName;
private Set<StuSub> stuSubs = new HashSet<StuSub>();
public Subject() {
}
public Subject(String subName) {
super();
this.subName = subName;
}
public Subject(String subName, Set<StuSub> stuSubs) {
this.subName = subName;
this.stuSubs = stuSubs;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getSubName() {
return this.subName;
}
public void setSubName(String subName) {
this.subName = subName;
}
public Set<StuSub> getStuSubs() {
return this.stuSubs;
}
public void setStuSubs(Set<StuSub> stuSubs) {
this.stuSubs = stuSubs;
}
}
StuSub:
public class StuSub {
private String id;
private Student student;
private Subject subject;
public StuSub() {
}
public StuSub(Student student, Subject subject) {
this.subject = subject;
this.student = student;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public Subject getSubject() {
return this.subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
public Student getStudent() {
return this.student;
}
public void setStudent(Student student) {
this.student = student;
}
}
映射文件:
Student.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="chapter4.model.Student" table="student">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="stuName" type="java.lang.String">
<column name="stuName" length="20" />
</property>
<set name="stuSubs">
<key>
<column name="stu_id" length="32" />
</key>
<one-to-many class="chapter4.model.StuSub" />
</set>
</class>
</hibernate-mapping>
Subject.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="chapter4.model.Subject" table="subject">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="subName" type="java.lang.String">
<column name="subName" length="20" />
</property>
<set name="stuSubs">
<key>
<column name="sub_id" length="32" />
</key>
<one-to-many class="chapter4.model.StuSub" />
</set>
</class>
</hibernate-mapping>
StuSub.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="chapter4.model.StuSub" table="stu_sub">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex"/>
</id>
<many-to-one name="subject" class="chapter4.model.Subject">
<column name="sub_id" length="32" />
</many-to-one>
<many-to-one name="student" class="chapter4.model.Student">
<column name="stu_id" length="32" />
</many-to-one>
</class>
</hibernate-mapping>
Dao层:
StudentDao:
public class StudentDao {
public void create(Student student) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.save(student);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public Student findById(Serializable id) throws Exception {
Session session = null;
Student student = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
student = (Student) session.get(Student.class, id);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return student;
}
}
SubjectDao:
public class SubjectDao {
public void create(Subject subject) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.save(subject);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public Subject findById(Serializable id) throws Exception {
Session session = null;
Subject subject = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
subject = (Subject) session.get(Subject.class, id);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return subject;
}
}
StuSubDao:
public class StuSubDao {
public void create(StuSub stuSub) throws Exception {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
session.save(stuSub);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
public StuSub findById(Serializable id) throws Exception {
Session session = null;
StuSub stuSub = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.getTransaction();
transaction.begin();
stuSub = (StuSub) session.get(StuSub.class, id);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
}
return stuSub;
}
}
测试文件:
Test:
public class Test {
public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
StuSubDao stuSubDao = new StuSubDao();
SubjectDao subjectDao = new SubjectDao();
//创建两个学生
Student student1 = new Student("张三");
Student student2 = new Student("李四");
//创建三门科目
Subject subject1 = new Subject("java");
Subject subject2 = new Subject("sql");
Subject subject3 = new Subject("javaScript");
//张三报了三门课
StuSub stuSub1 = new StuSub(student1, subject1);
StuSub stuSub2 = new StuSub(student1, subject2);
StuSub stuSub3 = new StuSub(student1, subject3);
//李四报了二门课
StuSub stuSub4 = new StuSub(student2, subject1);
StuSub stuSub5 = new StuSub(student2, subject2);
//保存学生入库
studentDao.create(student1);
studentDao.create(student2);
//保存科目入库
subjectDao.create(subject1);
subjectDao.create(subject2);
subjectDao.create(subject3);
//保存张三选修的科目入库
stuSubDao.create(stuSub1);
stuSubDao.create(stuSub2);
stuSubDao.create(stuSub3);
//保存李四选修的科目入库
stuSubDao.create(stuSub4);
stuSubDao.create(stuSub5);
//知道张三的ID,查找张三选修了哪几门科目
Student student = studentDao.findById("40285c8127aa1e9d0127aa1e9ed50001");
Set<StuSub> set1 = student.getStuSubs();
for(StuSub stuSub : set1){
System.out.println(stuSub.getSubject().getSubName());
}
//知道Java科目的ID,查找有哪些人修过Java科目
Subject subject = subjectDao.findById("40285c8127aa1e9d0127aa1e9fbf0005");
Set<StuSub> set2 = subject.getStuSubs();
for(StuSub stuSub : set2){
System.out.println(stuSub.getStudent().getStuName());
}
}
}