- 浏览: 1229788 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (718)
- HTML (13)
- JS基础 (23)
- JS应用 (40)
- AJAX (6)
- JSP相关 (12)
- JAVA基础 (52)
- JAVA应用 (74)
- APPLET (11)
- SWING\RCP (2)
- JAVA反射 (6)
- 设计模式 (26)
- 数据库设计 (20)
- Struts (35)
- Struts2 (12)
- Spring (22)
- Hibernate (45)
- Ibatis (18)
- mybatis (3)
- SSH (8)
- UML (5)
- WebService (3)
- XML (16)
- Log4j (7)
- WEB容器 (26)
- 数据结构 (36)
- Linux (34)
- Ruby on Rails (1)
- 其它技术 (27)
- IDE配置 (15)
- 项目实战 (2)
- Oracle (69)
- JAVA报表 (7)
- Android学习 (2)
- 博客链接 (1)
- 网络基础 (1)
- WEB集群 (1)
- .Net开发 (11)
- PB (4)
- 系统构建 (15)
最新评论
-
jnjeC:
牛逼啊哥们,讲得太好了
Maven仓库理解、如何引入本地包、Maven多种方式打可执行jar包 -
九尾狐的yi巴:
很好 感谢!
Itext中文处理(更新版) -
luweifeng1983:
有用的,重启一下嘛。
设置eclipse外部修改文件后自动刷新 -
Master-Gao:
设置了也不管用,怎么破呢?
设置eclipse外部修改文件后自动刷新 -
aigo_h:
锋子还有时间写博客,还是很闲哈!
Add directory entries问题
一、一对多单向关联
多对一与一对多类似
一对多映射中,只需要在一方的POJO中加入Set.
在一方的映射中加入:
<set name="students">
<key column="class_id"></key>
<one-to-many class="Student"/>
</set>
起到指示作用,指示在多方的表中加入一个外键.
Hibernate一对多单向关联映射 这种映射的本质是利用了多对一的关联映射的原理 多对一关联映射:是在多的一端添加一个外键维护多指向一的关联引用 一对多关联映射:是在多的一端添加一个外键维护一指向多的关联引用 也就是说,一对多和多对一的映射策略是一致的,只是站的角度不同 缺点: * 更新student表中的classesid字段时,需要对每一个student发出一个update的sql, 来更新classesid字段 * 如果将t_student表中的classesis设置为非空,则不能保存student数据,因为关系是由 classes维护的,在保存student时,还没有对应的classesid被生成
具体示例如下:
package com.lwf.hibernate.pojo; import java.util.HashSet; import java.util.Set; public class Classes { private int id; private String name; private Set students = new HashSet(); 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; } }
package com.lwf.hibernate.pojo; public class Student { private int id; private String name; private int age; 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 int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Classes.hbm.xml
<?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.lwf.hibernate.pojo"> <class name="Classes" table="t_classes"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="students" > <key column="class_id" ></key> <one-to-many class="Student" /> </set> </class> </hibernate-mapping>
Student.hbm.xml
<?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.lwf.hibernate.pojo"> <class name="Student" table="t_student"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <property name="age"/> </class> </hibernate-mapping>
具体的数据库结构:
mysql> desc student; +----------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | | class_id | int(11) | YES | MUL | NULL | | +----------+--------------+------+-----+---------+----------------+ 3 rows in set (0.06 sec) mysql> desc t_class; +-------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | +-------+--------------+------+-----+---------+----------------+
测试方法:
package com.lwf.hibernate.test; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import junit.framework.TestCase; import org.hibernate.Session; import com.lwf.hibernate.pojo.Classes; import com.lwf.hibernate.pojo.Student; import com.lwf.hibernate.util.HibernateUtil; public class One2Many_Test extends TestCase{ //从classes这一端来维护,即在单方维护,会产生insert和update语句. public void testClasses(){ Session session = HibernateUtil.getSession(); session.beginTransaction(); try{ Set students = new HashSet(); for(int i=0;i<5;i++){ Student s = new Student(); s.setName("name" + i); s.setAge((10 + i)); students.add(s); session.save(s); } Classes cla = new Classes(); cla.setName("class1"); cla.setStudents(students); session.save(cla); //先保存,最后根据class_id更新Student HibernateUtil.commit(session); }catch(Exception e){ HibernateUtil.roolback(session); }finally{ HibernateUtil.closeSession(session); } } public void testLoad(){ Session session = HibernateUtil.getSession(); session.beginTransaction(); try{ Classes s = (Classes)session.load(Classes.class, 1); Set student = s.getStudents(); for (Iterator iterator = student.iterator(); iterator.hasNext();) { Student stu = (Student) iterator.next(); System.out.println(stu.getName()); } HibernateUtil.commit(session); }catch(Exception e){ HibernateUtil.roolback(session); }finally{ HibernateUtil.closeSession(session); } } }
注意保存生成的语句:
Hibernate: insert into t_student (name, age) values (?, ?) Hibernate: insert into t_student (name, age) values (?, ?) Hibernate: insert into t_student (name, age) values (?, ?) Hibernate: insert into t_student (name, age) values (?, ?) Hibernate: insert into t_student (name, age) values (?, ?) Hibernate: insert into t_classes (name) values (?) Hibernate: update t_student set class_id=? where id=? Hibernate: update t_student set class_id=? where id=? Hibernate: update t_student set class_id=? where id=? Hibernate: update t_student set class_id=? where id=? Hibernate: update t_student set class_id=? where id=?
先保存student,再保存classes最后根据classes的id更新student的class_id
这实际上是由classes这方来维护两者的关联关系.
正常情况下关系应该由多的一方来维护,在双向关联中我们从多方来维护两者的关系.这样就可以避免update语句的出现.而是直接insert即可.
二、一对多双向关联
下面我们看看双向的一对多映射,实际上就是把一对多与多对一结合起来看.
Hibernate 一对多双向关联映射 一对多双向关联映射的方法: 在一一端: 在集合标签里面使用<key>标签来表明需要在对方的表中添加一个外键指向一一端。 在多一端: 使用<many-to-one>标签来映射。 需要注意:<key>标签所指定的外键字段名需要与<many-to-one>标签定义的外键字段名一致,否则便会造成引用数据的 丢失! -------------------------------------------------------------------------------------- 如果从一端来维护一对多双向关联的关系,hibernate会发出多余的update语句,所以 一般地情况下,我们便会从多一端来维护其关联关系! ----------------------------------------------------
在单向映射的基础上加上多对一关联即可.更改的文件:
package com.lwf.hibernate.pojo; public class Student { private int id; private String name; private int age; private Classes classes; 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 int getAge() { return age; } public void setAge(int age) { this.age = age; } public Classes getClasses() { return classes; } public void setClasses(Classes classes) { this.classes = classes; } }
Student.hbm.xml
<?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.lwf.hibernate.pojo"> <class name="Student" table="t_student"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <property name="age"/> <many-to-one name="classes" column="class_id"></many-to-one> </class> </hibernate-mapping>
即从Student的角度就是多对一,而从Classes角度就是一对多.
此时的表结构与单向的时候是一样的.
package com.lwf.hibernate.test; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import junit.framework.TestCase; import org.hibernate.Session; import com.lwf.hibernate.pojo.Classes; import com.lwf.hibernate.pojo.Student; import com.lwf.hibernate.util.HibernateUtil; public class One2Many_Test extends TestCase{ //从classes这一端来维护,即在单方维护,会产生insert和update语句. public void testClasses(){ Session session = HibernateUtil.getSession(); session.beginTransaction(); try{ Set students = new HashSet(); for(int i=0;i<5;i++){ Student s = new Student(); s.setName("name" + i); s.setAge((10 + i)); students.add(s); session.save(s); } Classes cla = new Classes(); cla.setName("class1"); cla.setStudents(students); session.save(cla); //先保存,最后根据class_id更新Student HibernateUtil.commit(session); }catch(Exception e){ HibernateUtil.roolback(session); }finally{ HibernateUtil.closeSession(session); } } //由于配置了双向关联,所以下面先保存了classes再保存student只有insert语句,没有update语句 public void testStudent(){ Session session = HibernateUtil.getSession(); session.beginTransaction(); try{ Classes cla = new Classes(); cla.setName("class111"); session.save(cla); for (int i = 0; i < 5; i++) { Student s = new Student(); s.setName("name111"+i); s.setClasses(cla); session.save(s); } HibernateUtil.commit(session); }catch(Exception e){ HibernateUtil.roolback(session); }finally{ HibernateUtil.closeSession(session); } } //从classes得到student,主要测试单向关联 public void testLoadClass(){ Session session = HibernateUtil.getSession(); session.beginTransaction(); try{ Classes s = (Classes)session.load(Classes.class, 1); Set student = s.getStudents(); for (Iterator iterator = student.iterator(); iterator.hasNext();) { Student stu = (Student) iterator.next(); System.out.println(stu.getName()); } HibernateUtil.commit(session); }catch(Exception e){ HibernateUtil.roolback(session); }finally{ HibernateUtil.closeSession(session); } } //从student得到classes,配置了双向关联后的测试 public void testLoadStudent(){ Session session = HibernateUtil.getSession(); session.beginTransaction(); try{ Student s = (Student)session.load(Student.class, 1); System.out.println(s.getName()); System.out.println(s.getClasses().getName()); HibernateUtil.commit(session); }catch(Exception e){ HibernateUtil.roolback(session); }finally{ HibernateUtil.closeSession(session); } } }
主要区别:
由于配置了双向关联,所以下面先保存了classes再保存student只有insert语句,没有update语句
以下是testStudent方法产生的SQL语句
Hibernate: insert into t_classes (name) values (?) Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?) Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?) Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?) Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?) Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?)
三、下面讨论一下关于INVERSE的用法:
关于inverse属性: inverse属性可以被设置到集合标签<set>上,表示在存储双向一对多关联映射的时候, 存储的是那一方的关联引用。默认情况下,inverse=“false”,所以,我们可以从一一端 或者多一端来维护两者之间的关系;如果我们设置inverse=“true”,则只能通过多一端来 维护两者之间的关系。inverse属性可以被用在一对多和多对多双向关联中; 注意:inverse属性只是在将数据持久化到数据库的过程中发挥作用.
主要看看上面双向关联中testClasses方法,当classes.hbm.xml文件如下时
<?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.lwf.hibernate.pojo"> <class name="Classes" table="t_classes"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="students" > <key column="class_id" ></key> <one-to-many class="Student" /> </set> </class> </hibernate-mapping>
我们知道上面的testClasses方法产生的sql语句是先insert再update,上面已经讲到是从一方来维护关联关系的.那么现在我们把classes.hbm.xml的set上面增加inverse="true"即
<set name="students" inverse="true"> <key column="class_id" ></key> <one-to-many class="Student" /> </set>
那么这时候testClasses方法产生的SQL语句是?
Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?) Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?) Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?) Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?) Hibernate: insert into t_student (name, age, class_id) values (?, ?, ?) Hibernate: insert into t_classes (name) values (?)
虽然只产生了insert语句,但因为t_classes插入语句在后,所以数据库里面对应的t_student的记录:
mysql> select * from t_student; +----+-------+------+----------+ | id | name | age | class_id | +----+-------+------+----------+ | 1 | name0 | 10 | NULL | | 2 | name1 | 11 | NULL | | 3 | name2 | 12 | NULL | | 4 | name3 | 13 | NULL | | 5 | name4 | 14 | NULL | +----+-------+------+----------+
显然class_id为空.没有更新.
即用了INVERSE,将强制要求从多的一方来维护关系.即当设置了INVERSE属性后,要求使用testStudent方法来做保存.
而INVERSE属性没有设置时,对于双向的一对多关联,我们即可以使用testClasses又可以使用testStudent方法进行保存,但是他们的区别是testClasses操作中有insert和update语句,而testStudent只有insert语句.显然使用testStudent即从多方来维护关联关系节约了资源...
- hibernate_one2many.rar (11.9 KB)
- 下载次数: 17
- hibernate_one2many_double.rar (12.8 KB)
- 下载次数: 17
发表评论
-
Hibernate抓取策略二
2010-05-11 17:56 1070在Classes与Student一对多映射中,我们将Set里面 ... -
Hibernate抓取策略一
2010-05-11 16:29 1315抓取策略指多表关联查询的时候,Hibernate会发出多条sq ... -
Hibernate查询缓存
2010-05-11 01:15 1611二级缓存中,如果不设置“查询缓存”,那么hibernate只会 ... -
Hibernate所需完整类库
2010-05-11 01:08 884附件为最新配置Hibernate所需的包. 由来: 一、下 ... -
Hibernate 二级缓存缺少包出现的异常
2010-05-10 23:29 2325由于二级缓存使用的包org.hibernate.cache.E ... -
转:Hibernate性能优化之二级缓存
2010-05-10 17:28 1132http://chenhongbin007.blog.163. ... -
Hibernate lazy加载FOR 单端关联
2010-05-10 00:54 1309Hibernate单端关联懒加载策略:即在<one-to ... -
Hibernate lazy加载FOR Connection
2010-05-10 00:28 1185Hibernate集合属性的懒加载策略: 在集合属性上, ... -
Hibernate lazy加载FOR Class
2010-05-09 23:51 1040lazy策略可以用在: * <class>标签 ... -
Hibernate性能优化:二级缓存
2010-05-06 16:48 1060hibernate二级缓存 定义步骤: 1、打开缓存, ... -
Hibernate性能优化:一级缓存
2010-05-06 16:33 1114一级缓存与session周期一致,二级缓存与sessionFa ... -
Hibernate悲观锁与乐观锁及事务管理机制
2010-05-06 11:57 1178引用: 悲观锁与乐观锁: http://www.iteye ... -
Hibernate学习笔记博客
2010-05-06 11:32 716网上也有人自学hibernate的笔记 http://hi. ... -
Hibernate与EJB的区别
2010-05-05 18:09 865Hibernate不支持分布式应用 -
Hibernate对象状态
2010-05-05 17:48 1767Hibernate对象有三种状态: 瞬时状态(Transie ... -
Hibernate HQL示例十二:DML更新、删除及与Hibernate持久化更新
2010-05-05 16:42 1962DML更新及删除 示例: package com.bjsx ... -
Hibernate HQL示例十一:分页查询
2010-05-05 16:21 1128分页查询: select * from t_student ... -
Hibernate HQL示例十:统计查询
2010-05-05 15:57 2108统计函数的使用 count(*) 等 package co ... -
Hibernate HQL示例九:连接查询
2010-05-05 15:38 3533inner join left out join rig ... -
Hibernate HQL示例八:查询对象导航及Implicit Join
2010-05-05 10:32 1680通过Student对象导航到class对象的id 如下: ...
相关推荐
不过,如果需要双向映射,`Course`也需要定义一个`<set>`元素,与`Student`的映射相对应。 通过这样的配置,Hibernate就能理解`Student`和`Course`之间的多对多关系,并在操作时自动处理关联表的插入、更新和删除。...
在Hibernate中,一对一关联映射分为单向和双向。单向一对一映射通常涉及一个实体持有另一个实体的引用,而双向一对一映射则意味着两个实体都可以互相引用。这种关联关系在数据库层面通常通过主键外键约束来实现,但...
首先,我们来看**一对多单向关联映射**。在这个关系中,一方(如班级)知道另一方(如学生),但另一方并不知道这一方。在对象模型中,这通常表现为一个类(如Classes)有一个集合属性(如Set),用来存储多个相关联...
通过以上内容,我们对Hibernate中的一对多单向关联映射有了全面的理解,包括其配置方式、代码实现、使用技巧以及需要注意的细节。在实际项目开发中,正确理解和运用这些知识能够有效地提升数据操作的效率和代码的可...
在本文中,我们将详细介绍Hibernate一对一唯一外键关联映射的概念、配置方法和实践应用。 一对一唯一外键关联映射的概念 在Hibernate中,一对一唯一外键关联映射是指两个实体之间的关联关系,其中一个实体作为外键...
包含《多对多双向关联映射》《多对一单向关联映射》《多对一双向关联映射》《一对多单向关联映射》等文档,并有图解及例子,非常适合新手学习,尤其是刚刚接触hibernate,对映射关系不清楚的。。。。
在数据库设计中,这种关联关系是常见的,例如一个用户可以有多个订单(一对多),一个订单对应一个用户(多对一),而一个商品可以被多个订单购买,同时一个订单也可以包含多个商品(一对多双向关联)。这个标题暗示...
在本教程中,我们将探讨如何实现一对一唯一外键关联映射,特别关注单向关联的情况。 ### 1. Hibernate一对一关联概述 一对一关联分为两种类型:共享主键关联(Primary Key Join)和唯一外键关联(Unique Foreign ...
本文主要探讨的是Hibernate中的两种关联关系:多对一单向关联和多对一双向关联。通过理解这两种关联方式,我们可以更好地设计和实现复杂的数据库模型。 首先,我们来看**多对一单向关联**。这种关联意味着一个实体...
本文主要关注Hibernate中的一个核心概念——一对一(One-to-One)、一对多(One-to-Many)和多对一(Many-to-One)关联映射,特别是关于“一到多”单向和双向关联映射的配置心得。 首先,让我们了解“一到多”关联...
在探讨“Hibernate一对多双向”这一主题时,我们首先需要...总之,“Hibernate一对多双向”关联在企业级应用中非常常见,通过深入理解其配置和实现原理,开发者可以更好地设计和优化数据库模型,以满足复杂业务需求。
总结,Hibernate的一对多关联映射提供了处理实体间多对一关系的能力,既可实现单向关联,也可实现双向关联。通过合理配置,可以优化数据加载策略,进行级联操作,并方便地进行数据的保存和查询。在实际开发中,理解...
在Hibernate中,一对多关联映射和多对一关联映射的区别在于维护的关系不同。多对一关联映射中,多的一端维护一的一端的关系,在加载多的一端时,可以将一的一端加载上来。一对多关联映射中,一的一端维护多的一端的...
总的来说,这篇博客和相关代码示例为开发者提供了一个理解和实现Hibernate中多对多单向关联的起点,帮助他们更好地处理复杂的数据库关系映射。学习和实践这部分内容对于提升Java后端开发能力,特别是使用Hibernate...