上一篇文章中我们将了多对一、一对多的单双边配置,这篇文章我们主要讲一下多对多的单双边配置
Hibernate入门教程 第四章
Hibernate多对多的配置
Hibernate多对多分为2中情况,就是第三张表(中间表)的问题,如果中间表中没有其他的数据是一种,如果第三张表中有其他数据是一种。我们下面将分别对这2中情况进行讲解,我们选择最简单的学生选课为例子。
一、中间表中没有其他字段
1、配置文件
学生类
public class Student200 implements java.io.Serializable { // Fields private Integer id; private String name; private Set<Course200> courses = new HashSet<Course200>(); // Constructors /** default constructor */ public Student200() { } /** full constructor */ public Student200(String name, Set courses) { this.name = name; this.courses = courses; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Set<Course200> getCourses() { return courses; } public void setCourses(Set<Course200> courses) { this.courses = courses; } }
学生类配置文件 Student200.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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.sunny.entity200.Student200" table="student200" catalog="test100"> <id name="id" type="java.lang.Integer"> <column name="student_id" /> <generator class="identity"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="20" /> </property> <set name="courses" table="t_student_score"> <key column="student_id"></key> <many-to-many class="com.sunny.entity200.Course200" column="course_id"></many-to-many> </set> </class> </hibernate-mapping>
班级类
public class Course200 implements java.io.Serializable { // Fields private Integer id; private String name; private Set<Student200> students = new HashSet<Student200>(); // Constructors /** default constructor */ public Course200() { } /** full constructor */ public Course200(String name) { this.name = name; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Set<Student200> getStudents() { return students; } public void setStudents(Set<Student200> students) { this.students = students; } }
班级类配置文件 Course200.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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.sunny.entity200.Course200" table="course200" catalog="test100"> <id name="id" type="java.lang.Integer"> <column name="course_id" /> <generator class="identity"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="20" /> </property> <set name="students" table="t_student_score"> <key column="course_id"></key> <many-to-many class="com.sunny.entity200.Student200" column="student_id"></many-to-many> </set> </class> </hibernate-mapping>
我们可以看到配置文件中用的多少many-to-many
2、数据库操作
1、插入数据
//插入数据 public static void fun1(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Transaction trans = session.beginTransaction(); Student200 stu = new Student200(); stu.setName("tomcat"); Course200 c1 = new Course200(); c1.setName("c++"); stu.getCourses().add(c1); Course200 c2 = new Course200(); c2.setName("java"); stu.getCourses().add(c2); session.save(stu); session.save(c1); session.save(c2); trans.commit(); session.close(); }
2、查询数据
//查询数据 public static void fun2(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Query query = session.createQuery("select s,s.name,c.name from Student200 s left join fetch s.courses c"); List<Object[]> list = query.list(); for(Object[] o : list){ System.out.println(o[1]+" "+o[2]); } }
这里我们查询的是部分数据,而且我们用的是fetch,上几张中我们将了lazy的用法,我们知道Hibernate中默认lazy为true,既我们开启了延时加载,所以我们要想从学生中抓取课程的信息要fetch。我要说明的是,这句select s,s.name,c.name from Student200 s left join fetch s.courses c 语句中不要fetch效果是一样,left join 和 left join fetch在这里产生的效果是一样的,不知道Hibernate中为什么要可以这2种用法。
3、更新数据
//更行数据 public static void fun3(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Transaction trans = session.beginTransaction(); Course200 c = (Course200)session.get(Course200.class, 1); c.setName("PHP"); session.save(c); trans.commit(); session.close(); }
4、删除数据
//删除数据 public static void fun4(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Transaction trans = session.beginTransaction(); Course200 c = (Course200)session.get(Course200.class, 2); session.delete(c); trans.commit(); session.close(); }二、中间表中有其他字段
中间表有其他字段在Hibernate中稍微有点不同,我们还以学生选课为例,我们要在第三张表中加入成绩这个字段,上面没有多余字段情况下,我们我们2个类,2个配置文件,如果中间表中有其他的字段,那么我们就必须要产生中间表的类和配置文件,而且在hibernate中,多对多将拆分成2个一对多的情况(当然有其他的配置,我们这里给出常规的配置情况)。
下面我们给出配置方式
1、配置文件
学生类
package com.sunny.entity202; import java.util.HashSet; import java.util.Set; /** * Student200 entity. @author MyEclipse Persistence Tools */ public class Student200 implements java.io.Serializable { // Fields private Integer studentId; private String name; private Set SCs = new HashSet(0);//SCs对应第三张表选课表 // Constructors /** default constructor */ public Student200() { } /** full constructor */ public Student200(String name, Set SCs) { this.name = name; this.SCs = SCs; } // Property accessors public Integer getStudentId() { return this.studentId; } public void setStudentId(Integer studentId) { this.studentId = studentId; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Set getSCs() { return this.SCs; } public void setSCs(Set SCs) { this.SCs = SCs; } }
学生配置文件
<?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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.sunny.entity202.Student200" table="student200" catalog="test100"> <id name="studentId" type="java.lang.Integer"> <column name="student_id" /> <generator class="identity"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="20" /> </property> <set name="SCs" inverse="true"> <key> <column name="student_id" not-null="true" /> </key> <one-to-many class="com.sunny.entity202.SC" /> </set> </class> </hibernate-mapping>
课程类
public class Course200 implements java.io.Serializable { // Fields private Integer courseId; private String name; private Set SCs = new HashSet(0); // Constructors /** default constructor */ public Course200() { } /** full constructor */ public Course200(String name, Set SCs) { this.name = name; this.SCs = SCs; } // Property accessors public Integer getCourseId() { return this.courseId; } public void setCourseId(Integer courseId) { this.courseId = courseId; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Set getSCs() { return this.SCs; } public void setSCs(Set SCs) { this.SCs = SCs; } }
课程配置文件
<?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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.sunny.entity202.Course200" table="course200" catalog="test100"> <id name="courseId" type="java.lang.Integer"> <column name="course_id" /> <generator class="identity"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="20" /> </property> <set name="SCs" inverse="true"> <key> <column name="course_id" not-null="true" /> </key> <one-to-many class="com.sunny.entity202.SC" /> </set> </class> </hibernate-mapping>
中间表,选课表类
package com.sunny.entity202; /** * SC entity. @author MyEclipse Persistence Tools */ public class SC implements java.io.Serializable { // Fields private Integer id; private Student200 student200; private Course200 course200; private Integer score; // Constructors /** default constructor */ public SC() { } /** minimal constructor */ public SC(Student200 student200, Course200 course200) { this.student200 = student200; this.course200 = course200; } /** full constructor */ public SC(Student200 student200, Course200 course200, Integer score) { this.student200 = student200; this.course200 = course200; this.score = score; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public Student200 getStudent200() { return this.student200; } public void setStudent200(Student200 student200) { this.student200 = student200; } public Course200 getCourse200() { return this.course200; } public void setCourse200(Course200 course200) { this.course200 = course200; } public Integer getScore() { return this.score; } public void setScore(Integer score) { this.score = score; } }
选课类配置文件
<?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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.sunny.entity202.SC" table="t_student_score" catalog="test100"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="identity" /> </id> <many-to-one name="student200" class="com.sunny.entity202.Student200" fetch="select"> <column name="student_id" not-null="true" /> </many-to-one> <many-to-one name="course200" class="com.sunny.entity202.Course200" fetch="select"> <column name="course_id" not-null="true" /> </many-to-one> <property name="score" type="java.lang.Integer"> <column name="score" /> </property> </class> </hibernate-mapping>
我们从上面配置可以看出,多对多被拆成了2个一对多
2、数据操作
这里我们就给出一个添加的操作,其他的都差不多
//插入数据 public static void fun1(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Transaction trans = session.beginTransaction(); Student200 stu = new Student200(); stu.setName("apache"); Course200 c = new Course200(); c.setName("java"); SC sc = new SC(); sc.setCourse200(c); sc.setStudent200(stu); sc.setScore(99); session.save(stu); session.save(c); session.save(sc); trans.commit(); session.close(); }
总结:我在多对多配置有多余字段的情况(多了成绩一个字段)中,我添加了一个主键id,在第一种情况中我没有添加id(选课表中只有2个字段学生id和课程id,联合主键),第二种情况我之所以要添加一个id是因为我如果不添加一个id,那么学生id和课程id就是联合主键,那么就要多出一个类来存储联合主键,看着麻烦,所以我这么做。
在多对多中配置中,像lazy、cascade、fetch、inverse 在前面我都说过,大家可以根据自已情况来选择一下配置,至于单边的配置,只要删除类中和配置文件中相关的地方就可以了,这里不再赘述
原文地址:http://blog.csdn.net/zhangpan19910604/article/details/46671297