one-to-many是一对多映射,如班级和学生的关系。
一对多也分为单向和双向之分。
package com.iteedu.hibernate; public class Student { private int id; private String name; 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; } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.iteedu.hibernate.Student" table="t_student"> <id name="id"> <generator class="native"/> </id> <property name="name"/> </class> </hibernate-mapping>
package com.iteedu.hibernate; import java.util.Set; public class Classes { private int id; private String name; private Set 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 getStudents() { return students; } public void setStudents(Set students) { this.students = students; } }
这里的一对多用集合Set来实现。
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.iteedu.hibernate"> <class name="Classes" table="t_classes"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="students"> <key column="classesid"/> <one-to-many class="Student"/> </set> </class> </hibernate-mapping>
这里主要说一下set的配制。
<one-to-many/>
这是确定Set中是什么对象,也通过class找到类和对应映射文件,就可以找到数据库中的表了。
<key column="classesid"/>
找到表怎么做关联,这就要一个外键来指定,key就是指定外键的列名的,是数据库中的列的名称。
保存
session.beginTransaction(); Student student1 = new Student(); student1.setName("QQ"); session.save(student1); Student student2 = new Student(); student2.setName("360"); session.save(student2); Set students = new HashSet(); students.add(student1); students.add(student2); Classes classes = new Classes(); classes.setName("ITEEDU"); classes.setStudents(students); //可以正确保存 session.save(classes); session.getTransaction().commit();
加载
session.beginTransaction(); Classes classes = (Classes)session.load(Classes.class, 1); System.out.println("classes.name=" + classes.getName()); Set students = classes.getStudents(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println("student.name=" + student.getName()); } session.getTransaction().commit();
一对多双向,一的一方不变,多的一方加上many-to-one配制。
private Classes classes; public Classes getClasses() { return classes; } public void setClasses(Classes classes) { this.classes = classes; }
<many-to-one name="classes" column="classesid"/>
其中column要和一的一端Set中的key相同。其实就是数据库要用同一个列关联。
保存
session.beginTransaction(); Classes classes = new Classes(); classes.setName("ITEEDU"); session.save(classes); Student student1 = new Student(); student1.setName("QQ"); student1.setClasses(classes); session.save(student1); Student student2 = new Student(); student2.setName("360"); student2.setClasses(classes); session.save(student2); session.getTransaction().commit();
加载
session.beginTransaction(); Student student = (Student)session.load(Student.class, 1); System.out.println("student.name=" + student.getName()); System.out.println("student.classes.name=" + student.getClasses().getName()); session.getTransaction().commit();
在一的一端维护关系的缺点:
如果将t_student表里的classesid字段设置为非空,则无法保存。
因为不是在student这一端维护关系,所以student不知道是哪个班的,所以需要发出多余的update语句来更新关系。
解决方法:
如果在一的一端维护一对多关联关系,hibernate会发出多余的udpate语句,所以我们一般在多的一端来维护关联关系。
关系反转inverse和级联cascade。
inverse主要用在一对多和多对多双向关联上,inverse可以被设置到集合标签<set>上,默认inverse为false,所以我们可以从一的一端和多的一端维护关联关系,如果设置成inverse为true,则我们只能从多的一端来维护关联关系。
<set name="students" inverse="true" cascade="all"> <key column="classesid"/> <one-to-many class="Student"/> </set>
保存示例:
session.beginTransaction(); Classes classes = new Classes(); classes.setName("ITEEDU"); Student student1 = new Student(); student1.setName("QQ"); student1.setClasses(classes); Student student2 = new Student(); student2.setName("360"); student2.setClasses(classes); Set students = new HashSet(); students.add(student1); students.add(student2); classes.setStudents(students); session.save(classes); session.getTransaction().commit();
在保存classes时,由于双向关联,学生设置了班级,所以先保存班级,再保存学生(级联后自动保存学生)。