首页 > 代码库 > hibernate关系映射(多对一)
hibernate关系映射(多对一)
对多一关系是最普遍也是最重要的一种对象关系,其中又包括了单向的多对一,单向的一对多以及双向的多对一关系
单向多对一
多的一方:学生(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>