Hibernate(多对多)
1、表的关系:
分别有三个表:课程表、学生表、分数表。课程和学生的关系是多对多的,因为一个学生对应多个课程,而一个课程被多个学生选修。如果用一对多、多对一的观点来看待课程和学生的关系显然是不对的,因为课程表和学生表中都没有外键。
因此,为了找到表之间多对多的关系,需要引入第三个表(分数表),分数表中含有课程表和学生表的主键,可以将两个本来没有关联的表通过第三个表连接起来。
2、实体关系表达:
学生:
public class Student { private Integer studentno; private String sname; private String sex; private String birthday; private String classno; private Float point; private String phone; private String email; private Set<Course> courses=new HashSet<Course>(); public Integer getStudentno() { return studentno; } public void setStudentno(Integer studentno) { this.studentno = studentno; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getBirthday() { return birthday; } public void setBirthday(String birthday) { this.birthday = birthday; } public String getClassno() { return classno; } public void setClassno(String classno) { this.classno = classno; } public Float getPoint() { return point; } public void setPoint(Float point) { this.point = point; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Set<Course> getCourses() { return courses; } public void setCourses(Set<Course> courses) { this.courses = courses; } @Override public String toString() { return "Student{" + "studentno=" + studentno + ", sname=\'" + sname + \'\\'\' + ", sex=\'" + sex + \'\\'\' + ", birthday=\'" + birthday + \'\\'\' + ", classno=\'" + classno + \'\\'\' + ", point=" + point + ", phone=\'" + phone + \'\\'\' + ", email=\'" + email + \'\\'\' + ", courses=" + courses + \'}\'; } }
课程:
public class Course { private Integer courseid; private double credit; private String courseno; private String cname; private String type; private Integer period; private Set<Student> students=new HashSet<Student>(); public Integer getCourseid() { return courseid; } public void setCourseid(Integer courseid) { this.courseid = courseid; } public double getCredit() { return credit; } public void setCredit(double credit) { this.credit = credit; } public String getCourseno() { return courseno; } public void setCourseno(String courseno) { this.courseno = courseno; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public String getType() { return type; } public void setType(String type) { this.type = type; } public Integer getPeriod() { return period; } public void setPeriod(Integer period) { this.period = period; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } @Override public String toString() { return "Course{" + "courseid=" + courseid + ", credit=" + credit + ", courseno=\'" + courseno + \'\\'\' + ", cname=\'" + cname + \'\\'\' + ", type=\'" + type + \'\\'\' + ", period=" + period + ", students=" + students + \'}\'; } }
两个实体中,分别创建了两个set集合存储对方实体对象。
3、多对多的配置:
(1)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="pers.zhb.domain"> <class name="Student" table="student"> <id name="studentno" column="studentno" > <generator class="native"></generator> </id> <property name="birthday" column="birthday"></property> <property name="classno" column="classno"></property> <property name="email" column="email"></property> <property name="phone" column="phone"></property> <property name="sex" column="sex"></property> <property name="sname" column="sname"></property> <property name="point" column="point"></property> <set name="courses" table="score" inverse="true"> <key column="studentno"></key> <many-to-many class="Course" column="courseid"></many-to-many> </set> </class> </hibernate-mapping>
前面的内容大多是对主键和普通属性的配置,主要是对于一对多关系的配置:
<set name="courses" table="score" inverse=“true”> <key column="studentno"></key> <many-to-many class="Course" column="courseid"></many-to-many> </set>
name属性:对应的多的一方的集合名字。
table:联系student表和course表关系的第三个表。
column:student表的外键。
class:对应的多的一方(课程)的类名。
column:对应的多的一方的类的主键。
inverse:等于true相当于让学生一方放弃维护关系,因为双方同时维护关系会导致错误。
(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="pers.zhb.domain"> <class name="Course" table="course"> <id name="courseid" column="courseid" > <generator class="native"></generator> </id> <property name="courseno" column="courseno"></property> <property name="cname" column="cname"></property> <property name="credit" column="credit"></property> <property name="type" column="type"></property> <property name="period" column="period"></property> <set name="students" table="score"> <key column="courseid"></key> <many-to-many class="Student" column="studentno"></many-to-many> </set> </class> </hibernate-mapping>
(3)虽然联系student表和course表需要第三个表score,但是并不需要对score表进行配置。
4、多对多的基本操作:
(1)学生和课程的多对多添加:
public static void testadd() { Session session = HibernateUtils.openSession();//获得session Transaction transaction = session.beginTransaction();//开启事务 Student student=new Student(); student.setSname("翟"); student.setPoint(123f); student.setClassno(46); student.setSex("男"); student.setBirthday("2019-11-11"); student.setPhone("18739496522"); student.setEmail("34288334@qq.com"); Student student1=new Student(); student1.setSname("翟hb"); student1.setPoint(666f); student1.setClassno(46); student1.setSex("女"); student1.setBirthday("2019-11-11"); student1.setPhone("18739496522"); student1.setEmail("34288334@qq.com"); Course course=new Course(); course.setCourseno("123"); course.setCname("算法设计"); course.setType("必修"); course.setCredit(4); course.setPeriod(22); Course course1=new Course(); course.setCourseno("456"); course1.setCname("网络"); course1.setCredit(2); course1.setPeriod(12); course1.setType("必修"); student.getCourses().add(course); student.getCourses().add(course1); student1.getCourses().add(course); student1.getCourses().add(course1); session.save(student); session.save(student1); session.save(course); session.save(course1); transaction.commit();//提交事务 session.close();//关闭资源 }
分别创建了两个学生对象和两个课程对象,在学生类的集合中添加两个课程对象,同样,在课程类的集合中添加两个学生对象,并将他们转换为持久化状态。
运行结果:
学生:
课程:
分数:
(2)为一个学生添加课程:
public static void testadd1(){ Session session = HibernateUtils.openSession();//获得session Transaction transaction = session.beginTransaction();//开启事务 Student student=session.get(Student.class,1);//获得要添加的学生对象 Course course=new Course();//创建课程对象 course.setCname("算法设计"); course.setType("必修"); course.setCredit(4); course.setPeriod(22); course.setCourseno("123"); student.getCourses().add(course); session.save(course);//转化为持久态 transaction.commit();//提交事务 session.close();//关闭资源 }
运行结果:
学生:
课程:
分数:
可以看到学号为1的学生增加了课程id为1的课程。
(2)删除操作:
public static void testDel(){ Session session = HibernateUtils.openSession();//获得session Transaction transaction = session.beginTransaction();//开启事务 Student student=session.get(Student.class,1);//获得要添加的学生对象 Course course=session.get(Course.class,1); Course course1=session.get(Course.class,2); student.getCourses().remove(course); student.getCourses().remove(course1); transaction.commit();//提交事务 session.close();//关闭资源 }
5、级联操作:
(1)级联保存:
public static void testadd1(){ Session session = HibernateUtils.openSession();//获得session Transaction transaction = session.beginTransaction();//开启事务 Student student=session.get(Student.class,1);//获得要添加的学生对象 Course course=new Course();//创建课程对象 course.setCname("算法设计"); course.setType("必修"); course.setCredit(4); course.setPeriod(22); course.setCourseno("123"); student.getCourses().add(course); transaction.commit();//提交事务 session.close();//关闭资源 }
<?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="pers.zhb.domain">
<class name="Course" table="course">
<id name="courseid" column="courseid" >
<generator class="native"></generator>
</id>
<property name="courseno" column="courseno"></property>
<property name="cname" column="cname"></property>
<property name="credit" column="credit"></property>
<property name="type" column="type"></property>
<property name="period" column="period"></property>
<set name="students" table="score" cascade="save-update"><!--一对多关系配置-->
<key column="courseid"></key><!--指定了集合表的外键-->
<many-to-many class="Student" column="studentno"></many-to-many>
</set>
</class>
</hibernate-mapping>
与一对多、多对一相似,级联操作的运用可以减少代码量。
(2)级联删除:
可以使用,但是危险系数较高。