【Hibernate系列】(六):关联映射之一对多
2016-02-13 20:33
411 查看
前言
在阅读本篇博客之前,请先对多对一关联映射有所了解,可参考【Hibernate系列】(五):关联映射之多对一 。在上篇博客中,我们已经强调过,多对一和一对多的关联映射原理都是在多的一端加入外键。它们在对象模型中的区别就是从谁能看到谁的问题。如:在上篇文章的例子中,通过user可以加载出group来,但是不能通过group来加载user。这篇文章,我们着重强调单纯一对多关系的配置,以及一对多和多对一同时存在时的配置。一对多
关系模型和映射原理
这里只是方便大家和后面的代码对应。模型和原理同多对一。配置
★Classes.java[code]package com.bjpowernode.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; } }
★Classes.hbm.xml
[code]<?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.bjpowernode.hibernate.Classes" table="t_classes"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="students"> <!--指定外键字段名称--> <key column="classesid"/> <!--通过class属性指定关联集合中存储的实体类型--> <one-to-many class="com.bjpowernode.hibernate.Student"/> </set> </class> </hibernate-mapping>
Students.java和Student.hbm.xml中未进行任何配置,这里省略它们的代码。
对象的存储和加载
因为只在一端进行了配置,所以我们可以猜到能够通过Classes加载Student,反之则不行。而且这个关联关系也是由Classes来维护的,所以存储的时候,应该先存储Student,再存储Classes。即:关系由谁维护谁就后存储,另外的对象先存储。[code]public void testSave2() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); Student student1 = new Student(); student1.setName("张三"); session.save(student1); Student student2 = new Student(); student2.setName("李四"); session.save(student2); Classes classes = new Classes(); classes.setName("动力节点"); Set students = new HashSet(); students.add(student1); students.add(student2); classes.setStudents(students); //可以成功保存数据 //但是会发出多余的update语句来维持关系 session.save(classes); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } }
因为关系由class维护,所以先存储student,但是存储student的时候,还不知道classesid是什么,所以代码运行时会打印出以下结果:在save的时候插入数据,在commit的时候更新(外键)。
Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_classes (name) values (?)
Hibernate: update t_student set classesid=? where id=?
Hibernate: update t_student set classesid=? where id=?
发的语句越多说明和数据库交互越多,影响性能。
加载此处省略,可以通过classes加载student。
一对多和多对一结合
单纯的多对一,我们可以通过“多”加载“一”,不能通过“一”加载“多”。单纯的一对多,我们可以通过“一”加载“多”,不能通过“多”加载“一”,同时还存在影响性能的弊端。
所以,我们可能会单独使用多对一,但是很少会单独的使用一对多。
那么,如何能满足我们的需求,又能避免以上缺点呢?
配置
我们采取的方式一对多和多对一两个关系都配置上,只是关系由多的一方维护,也就是最关键的地方即在一的一端将inverse属性设置为true。一的一端只修改了配置文件。
[code]<hibernate-mapping> <class name="com.bjpowernode.hibernate.Classes" table="t_classes"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <!--inverse设置为true,关系由对端维护--> <set name="students" inverse="true"> <key column="classesid"/> <one-to-many class="com.bjpowernode.hibernate.Student"/> </set> </class> </hibernate-mapping>
多的一端的配置参考上一篇文章即可,这里省略.
存储就可以按多对一的时候的存储步骤进行存储了。此时两个对象也可以相互加载了。具体代码参考上一篇博客。
总结
通过多对一和一对多关联关系的学习,我们可以归纳出,配置<many-to-one>或
<one-to-many>标签决定的是能否加载关联对象;但是关系由谁维护,决定如何存储对象。
相关文章推荐
- hdu1248 寒冰王座(完全背包)
- Leetcode 110 判断一颗二叉树是否是平衡二叉树
- GCC
- FPGA中的时序分析(四)
- neuq oj 1018 A+B again C语言
- LeetCode 2015.7.15 27,20,19,14,232,118
- FPGA中的时序分析(三)
- 自己写的一个vii总结
- 字符串_笔记
- 关于coursera上Learning How to Learn课程的读书笔记
- 懒加载的一些理解
- Java中泛型中的几个符号
- LeetCode 2015.7.13 9,21,104,6,191,198,204,225
- bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)
- iOS 获取项目文件路径
- 杭电1059Windows Message Queue
- LeetCode 2015.7.10 26,58,226
- 一致性Hash算法
- LeetCode 2015.7.9 66,67,70,83,88,100
- 算法精讲学习笔记 队列和栈