对多一关系是最普遍也是最重要的一种对象关系,其中又包括了单向的多对一,单向的一对多以及双向的多对一关系
单向多对一
多的一方:学生(Student)
一的一方:班级(Grade)
班级类的定义以及hbm文件配置如下
1 public class Grade { 2 private int id; 3 private String name; 4 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.Grade" table="grade"> 7 <id name="id" column="id"> 8 <generator class="increment"></generator> 9 </id> 10 11 <property name="name" column="name"></property> 12 </class> 13 14 </hibernate-mapping>
学生类的定义以及hbm文件配置如下
1 public class Student { 2 private int id; 3 private String name; 4 private Grade grade; 5 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.Student" table="student"> 7 <id name="id" column="id"> 8 <generator class="increment"></generator> 9 </id> 10 11 <property name="name" type="java.lang.String"> 12 <column name="name" length="50" /> 13 </property> 14 15 <many-to-one name="grade" column="gradeid"></many-to-one> 16 </class> 17 18 </hibernate-mapping>
测试程序
1 public class HibernateTest { 2 public static void main(String[] args) { 3 Session session = HibernateFactory.currentSession(); 4 Transaction tx = session.beginTransaction(); 5 6 Grade grade = new Grade(); 7 grade.setName("grade1"); 8 9 Student student1 = new Student(); 10 student1.setName("student1"); 11 student1.setGrade(grade); 12 13 Student student2 = new Student(); 14 student2.setName("student2"); 15 student2.setGrade(grade); 16 17 session.save(grade); 18 session.save(student1); 19 session.save(student2); 20 21 tx.commit(); 22 session.close(); 23 } 24 }
结果
单向一对多
多的一方:学生(Student)
一的一方:班级(Grade)
学生类的定义以及hbm文件配置如下
1 public class Student { 2 private int id; 3 private String name; 4 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.Student" table="student"> 7 <id name="id" column="id"> 8 <generator class="increment"></generator> 9 </id> 10 11 <property name="name"></property> 12 </class> 13 14 </hibernate-mapping>
班级类的定义以及hbm文件配置如下
1 public class Grade { 2 private int id; 3 private String name; 4 private Set<Student> students = new HashSet<Student>(); 5 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.Grade" table="grade"> 7 <id name="id" column="id"> 8 <generator class="increment"></generator> 9 </id> 10 11 <property name="name" column="name"></property> 12 <set name="students"> 13 <key column="grade_id"/> 14 <one-to-many class="com.zlt.hibernatedemo.Student"/> 15 </set> 16 </class> 17 18 </hibernate-mapping>
测试程序
1 public class HibernateTest { 2 public static void main(String[] args) { 3 Session session = HibernateFactory.currentSession(); 4 Transaction tx = session.beginTransaction(); 5 6 Grade grade = new Grade(); 7 grade.setName("grade1"); 8 9 Student student1 = new Student(); 10 student1.setName("student1"); 11 12 Student student2 = new Student(); 13 student2.setName("student2"); 14 15 grade.getStudents().add(student1); 16 grade.getStudents().add(student2); 17 18 session.save(grade); 19 session.save(student1); 20 session.save(student2); 21 22 tx.commit(); 23 session.close(); 24 } 25 }
结果
<set>标签中可以设置cascade属性(all,save-update,delete,none)
当不设置cascade时,保存时需要执行三条语句
1 session.save(grade); 2 session.save(student1); 3 session.save(student2);
当设置cascade="all"后对某个grade的操作会级联到它student,所以只需执行session.save(grade)就可以同时插入三条数据到数据库
不设置cascade时,执行session.delete(grade);会把grade从数据库中删去,同时把student关联到这个grade的外键gradeid的值置为空;而设置了cascade后,删除了grade同时会把该grade对应的student对象从数据库中删去
<set>标签中也可以设置inverse属性(true,false)
inverse="false"(默认)生成的sql语句
Hibernate: insert into grade (name, id) values (?, ?)
Hibernate: insert into student (name, id) values (?, ?)
Hibernate: insert into student (name, id) values (?, ?)
Hibernate: update student set grade_id=? where id=?
Hibernate: update student set grade_id=? where id=?
inverse="true"生成的sql语句
Hibernate: insert into grade (name, id) values (?, ?)
Hibernate: insert into student (name, id) values (?, ?)
Hibernate: insert into student (name, id) values (?, ?)
同时数据库并没有关联三条数据
它意味着 grade不再作为主控方,而将关联关系的维护工作交给关联对象student来完成。在保存grade时,grade不在关心student的gradeid属性,必须由student自己去维护,即设置student.setGrade(grade); 如果需要通过student来维护关联关系,那么这个关联关系转换成双向关联。
双向关联
学生
1 public class Student { 2 private int id; 3 private String name; 4 private Grade grade; 5 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.Student" table="student"> 7 <id name="id" column="id"> 8 <generator class="increment"></generator> 9 </id> 10 11 <property name="name" type="java.lang.String"> 12 <column name="name" length="50" /> 13 </property> 14 15 <many-to-one name="grade" column="gradeid"></many-to-one> 16 </class> 17 18 </hibernate-mapping>
班级
1 public class Grade { 2 private int id; 3 private String name; 4 private Set<Student> students = new HashSet<Student>(); 5 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class name="com.zlt.hibernatedemo.Grade" table="grade"> 7 <id name="id" column="id"> 8 <generator class="increment"></generator> 9 </id> 10 11 <property name="name" column="name"></property> 12 13 <set name="students" inverse="true" cascade="all"> 14 <key column="gradeid"/> 15 <one-to-many class="com.zlt.hibernatedemo.Student"/> 16 </set> 17 </class> 18 19 </hibernate-mapping>
测试程序
public class HibernateTest { public static void main(String[] args) { Session session = HibernateFactory.currentSession(); Transaction tx = session.beginTransaction(); Grade grade = new Grade(); grade.setName("grade1"); Student student1 = new Student(); student1.setName("student1"); Student student2 = new Student(); student2.setName("student2"); //只需要session.save(grade);就能插入三条数据,需要先设置cascade grade.getStudents().add(student1); grade.getStudents().add(student2); //因为grade中inverse设置为ture,所以需要由student维护关联关系,设置graidid student1.setGrade(grade); student2.setGrade(grade); session.save(grade); tx.commit(); session.close(); } }
结果:
产生3条sql语句(如果用一的那端维护关联关系,会产生5条sql,所以在多的一方设置inverse="true",有助于性能的改善)
Hibernate: insert into grade (name, id) values (?, ?)
Hibernate: insert into student (name, gradeid, id) values (?, ?, ?)
Hibernate: insert into student (name, gradeid, id) values (?, ?, ?)
自身一对多配置
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 3 4 <hibernate-mapping> 5 <class name="Category" table="category"> 6 <id name="id" type="string"> 7 <column name="id"></column> 8 <generator class="uuid"></generator> 9 </id> 10 11 <property name="name" column="name" type="string"></property> 12 13 <set name="chidrenCategories" cascade="all" inverse="true"> 14 <key column="category_id"></key> 15 <one-to-many class=" Category"/> 16 </set> 17 18 <many-to-one name="parentCategory" column="category_id"></many-to-one> 19 20 </class> 21 </hibernate-mapping>