【SSH快速进阶】——Hibernate 多对一映射 和 一对多映射
2015-12-22 11:42
549 查看
上两篇文章说了一对一映射,这里说一下多对一 和 一对多的映射情况。
![](http://img.blog.csdn.net/20151217113826179)
现实中有很多场景需要用到多对一或者一对多,比如上面这两个类图所展现出来的,一般情况下,一个部门会有多名员工,一名员工只在一个部门任职。
多对一关联映射
在上面的场景中,对于Employee来说,它跟Department的关系就是多对一。
PO对象
Employee.java
Department.java
配置多对一关系时,设计po类时,除了写出最基本的属性(比如Employee的id、name),在对应“多”的那个类(比如Employee.java)中添加对应“一”那个类的引用(比如上面的department)。
映射文件
Employee.hbm.xml
Department.hbm.xml
映射文件中的内容基本上跟它关联的类中的字段都是对应的。主键配置在
运行代码执行的建表语句为:
从建表语句中可以看出来,t_employee表中的外键departmentid与t_department表中的主键相关联。
生成的表结构如下:
![](http://img.blog.csdn.net/20151217210714077)
下面进行简单测试
插入测试
一执行,发现报错了:org.hibernate.TransientObjectException,一看错误就知道,这是因为department还在Transient状态时,session是不能对其操作的。所以可以在事务提交之前先save一下department:
这样就可以成功插入了:
![](http://img.blog.csdn.net/20151217202601366)
还有一种更简单的方法,就是在映射文件Employee.hbm.xml的
Employee.hbm.xml
cascade表示两个对象之间的操作为联动关系,即对一个对象执行了操作之后,对其指定的级联对象也要进行相同的操作。Hibernate文档对cascade的解释为:
"cascade(级联) (可选): 指明哪些操作会从父对象级联到关联的对象。它的值代表着Hibernate基本操作的名称, persist, merge, delete, save-update, evict, replicate, lock, refresh……"
查询测试
测试结果:
一对多关联映射
既然Employee对Department的关系是多对一,那么反之,Department对Employee就是一对多的关系。
所以要在Department的PO类中增加一个Employee对象的集合。这个集合可以是set、list、map甚至array等容器,由于set中的对象不可重复,并且性能更高,所以一般用set。
PO对象
Department.java
Employee.java
映射文件
Employee.hbm.xml
Department.hbm.xml
映射文件Department.hbm.xml中添加了set标签,对应Department类中的集合employees,表示一个Department对象对应多个Employee对象。
插入测试
插入结果:
![](http://img.blog.csdn.net/20151221211814054)
查询测试
控制台输出内容为:
由此可见,一对多的配置中,默认为延迟加载,相当于lazy=”true”。
给映射文件中
比较
相同点:映射原理基本一致,建表时,都是在“多”的一端添加外键指向“一”的一端。
区别:维护的关系不同
多对一维护的关系:多指向一的关系,加载“多”的时候可以把“一”也加载出来;
一对多维护的关系:一指向多的关系,加载“一”的时候可以把“多”也加载出来;
【 转载请注明出处——胡玉洋《【SSH快速进阶】——Hibernate 多对一映射 和 一对多映射》】
现实中有很多场景需要用到多对一或者一对多,比如上面这两个类图所展现出来的,一般情况下,一个部门会有多名员工,一名员工只在一个部门任职。
多对一关联映射
在上面的场景中,对于Employee来说,它跟Department的关系就是多对一。
PO对象
Employee.java
[code]public class Employee { public int id; public String name; public Department department; //getter、setter }
Department.java
[code]public class Department { public int id; public String name; //getter、setter }
配置多对一关系时,设计po类时,除了写出最基本的属性(比如Employee的id、name),在对应“多”的那个类(比如Employee.java)中添加对应“一”那个类的引用(比如上面的department)。
映射文件
Employee.hbm.xml
[code]<hibernate-mapping package="org.hibernate.test" > <class name="com.danny.hibernate.Employee" table="t_employee"> <id name="id" type="int"> <generator class="native"/> </id> <property name="name"/> <many-to-one name="department" column="departmentid"/> </class> </hibernate-mapping>
Department.hbm.xml
[code]<hibernate-mapping package="org.hibernate.test" > <class name="com.danny.hibernate.Department" table="t_department"> <id name="id"> <generator class="native"/> </id> <property name="name"/> </class> </hibernate-mapping>
映射文件中的内容基本上跟它关联的类中的字段都是对应的。主键配置在
<id></id>中,基本字段配置在
<property/>中,对其他类的引用配置在
<many-to-one/>中。
运行代码执行的建表语句为:
[code]alter table t_employee drop foreign key FKFDCF5A196E78D697 drop table if exists t_department drop table if exists t_employee create table t_department (id integer not null auto_increment, name varchar(255), primary key (id)) create table t_employee (id integer not null auto_increment, name varchar(255), departmentid integer, primary key (id)) alter table t_employee add index FKFDCF5A196E78D697 (departmentid), add constraint FKFDCF5A196E78D697 foreign key (departmentid) references t_department (id)
从建表语句中可以看出来,t_employee表中的外键departmentid与t_department表中的主键相关联。
生成的表结构如下:
下面进行简单测试
插入测试
[code]session.beginTransaction(); Department department=new Department(); department.setName("信息部"); Employee employee1=new Employee(); employee1.setName("小胡"); employee1.setDepartment(department); Employee employee2=new Employee(); employee2.setName("小玉"); employee2.setDepartment(department); session.save(employee1); session.save(employee2); session.getTransaction().commit();
一执行,发现报错了:org.hibernate.TransientObjectException,一看错误就知道,这是因为department还在Transient状态时,session是不能对其操作的。所以可以在事务提交之前先save一下department:
[code]session.beginTransaction(); Department department=new Department(); department.setName("信息部"); Employee employee1=new Employee(); employee1.setName("小胡"); employee1.setDepartment(department); Employee employee2=new Employee(); employee2.setName("小玉"); employee2.setDepartment(department); session.save(department); session.save(employee1); session.save(employee2); session.getTransaction().commit();
这样就可以成功插入了:
还有一种更简单的方法,就是在映射文件Employee.hbm.xml的
<many-to-one/>中配置
cascade属性,值为
"save-update":
Employee.hbm.xml
[code]<hibernate-mapping package="org.hibernate.test" > <class name="com.danny.hibernate.Employee" table="t_employee"> <id name="id" type="int"> <generator class="native"/> </id> <property name="name"/> <many-to-one name="department" column="departmentid" cascade="save-update"/> </class> </hibernate-mapping>
cascade表示两个对象之间的操作为联动关系,即对一个对象执行了操作之后,对其指定的级联对象也要进行相同的操作。Hibernate文档对cascade的解释为:
"cascade(级联) (可选): 指明哪些操作会从父对象级联到关联的对象。它的值代表着Hibernate基本操作的名称, persist, merge, delete, save-update, evict, replicate, lock, refresh……"
查询测试
[code]session.beginTransaction(); Employee employee=(Employee)session.load(Employee.class, 1); System.out.println("employee的name:"+employee.getName()); System.out.println("department的name:"+employee.getDepartment().getName()); session.getTransaction().commit();
测试结果:
[code]employee的name:小玉 department的name:信息部
一对多关联映射
既然Employee对Department的关系是多对一,那么反之,Department对Employee就是一对多的关系。
所以要在Department的PO类中增加一个Employee对象的集合。这个集合可以是set、list、map甚至array等容器,由于set中的对象不可重复,并且性能更高,所以一般用set。
PO对象
Department.java
[code]public class Department { public int id; public String name; public Set<Employee> employees; //getter、setter }
Employee.java
[code]public class Employee { public int id; public String name; //getter、setter }
映射文件
Employee.hbm.xml
[code]<hibernate-mapping package="org.hibernate.test" > <class name="com.danny.hibernate.Employee" table="t_employee"> <id name="id" type="int"> <generator class="native"/> </id> <property name="name"/> </class> </hibernate-mapping>
Department.hbm.xml
[code]<hibernate-mapping package="org.hibernate.test" > <class name="com.danny.hibernate.Department" table="t_department"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name=employees> <key column="departmentid"></key><!-- "多"的一方关联"一"的一方的外键 --> <one-to-many class="com.bjpowernode.hibernate.Employee"/><!-- 一个Department对象对应多个Employee对象 --> </set> </class> </hibernate-mapping>
映射文件Department.hbm.xml中添加了set标签,对应Department类中的集合employees,表示一个Department对象对应多个Employee对象。
插入测试
[code]session.beginTransaction(); Employee employee1=new Employee(); employee1.setName("小玉玉"); Employee employee2=new Employee(); employee2.setName("小洋洋"); Set<Employee> employees=new HashSet<Employee>(); employees.add(employee1); employees.add(employee2); Department department=new Department(); department.setName("信息部"); department.setEmployees(employees); session.save(employee1); session.save(employee2); session.save(department); session.getTransaction().commit();
插入结果:
查询测试
[code]session.beginTransaction(); Department department=(Department)session.load(Department.class,1); System.out.println("department的name:"+department.getName()); System.out.println("department的employee有:"); for(Employee employee:department.getEmployees()){ System.out.print(" "+employee.getName()); } session.getTransaction().commit();
控制台输出内容为:
[code]Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from t_department department0_ where department0_.id=? department的name:信息部 department的employee有:Hibernate: select employees0_.departmentid as departme3_1_, employees0_.id as id1_, employees0_.id as id1_0_, employees0_.name as name1_0_ from t_employee employees0_ where employees0_.departmentid=? 小洋洋 小玉玉
由此可见,一对多的配置中,默认为延迟加载,相当于lazy=”true”。
给映射文件中
<set>标签的属性
lazy设置为
false时,不会延迟加载,即查询Department的时候,会把属于该Department的Employee全部查询出来。控制台输出内容为:
[code]Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from t_department department0_ where department0_.id=? Hibernate: select employees0_.departmentid as departme3_1_, employees0_.id as id1_, employees0_.id as id1_0_, employees0_.name as name1_0_ from t_employee employees0_ where employees0_.departmentid=? department的name:信息部 department的employee有: 小洋洋 小玉玉
比较
相同点:映射原理基本一致,建表时,都是在“多”的一端添加外键指向“一”的一端。
区别:维护的关系不同
多对一维护的关系:多指向一的关系,加载“多”的时候可以把“一”也加载出来;
一对多维护的关系:一指向多的关系,加载“一”的时候可以把“多”也加载出来;
【 转载请注明出处——胡玉洋《【SSH快速进阶】——Hibernate 多对一映射 和 一对多映射》】
相关文章推荐
- POJ1037A decorative fence(动态规划+排序计数+好题)
- Java API —— HashMap类 & LinkedHashMap类
- 有些星座天生不适合干有些事情,如果一定要为之恐怕就会落到饿死的地步了!你知道自己这个星座有哪些事情是容易让自己饿死的吗?
- 在Linux系统中安装web端的远程连接工具Wetty
- Tab不同子对话框间函数互相调用
- 安全科普:理解SSL(https)中的对称加密与非对称加密
- 携程网移动端首页-学习与自我分析
- Pike学习笔记
- spring-mvc环境搭建及helloworld的demo实现
- JS控制按钮10秒钟后可用的方法
- Unity3D导入MAX文件的一些问题。不断更新。。。
- ZSTUOJ 4212 String Game
- ssh2的整合
- Oracle11g数据库导入Oracle10g问题
- Think In Java 读后感
- HTML5 预览预加载文件,图片
- Hive的那些事儿?
- Xcode7.1以上版本的第三方库的导入解决问号问题
- Mac上eclipse安装SVN+JavaHL
- Linux聊天室项目 -- ChatRome(select实现)