`
xhy0422
  • 浏览: 281146 次
社区版块
存档分类
最新评论

hibernate 中 inverse的设置对效率的影响

阅读更多
java 代码

 

  1. 双向关联与inverse设定    
  2.  之前我们对User与Room作了单向的多对一以及反过来的一对多关联,我们也可以让User与Room彼此参考,形成双向关联,就User与Room对象,具体来说,就是将程序如下设计:    
  3. User.java    
  4. package onlyfun.caterpillar;    
  5.   
  6. public class User {    
  7. private long id;    
  8. private String name;    
  9. private Room room;    
  10.   
  11. public long getId() {    
  12. return id;    
  13. }    
  14. public void setId(long id) {    
  15. this.id = id;    
  16. }    
  17. public String getName() {    
  18. return name;    
  19. }    
  20. public void setName(String name) {    
  21. this.name = name;    
  22. }    
  23. public Room getRoom() {    
  24. return room;    
  25. }    
  26.   
  27. public void setRoom(Room room) {    
  28. this.room = room;    
  29. }    
  30. }    
  31. Room.java    
  32. package onlyfun.caterpillar;    
  33.   
  34. import java.util.*;    
  35.   
  36. public class Room {    
  37. private long id;    
  38. private String address;    
  39. private Set users = new HashSet();    
  40.   
  41. public long getId() {    
  42. return id;    
  43. }    
  44. public void setId(long id) {    
  45. this.id = id;    
  46. }    
  47. public String getAddress() {    
  48. return address;    
  49. }    
  50. public void setAddress(String address) {    
  51. this.address = address;    
  52. }    
  53. public Set getUsers() {    
  54. return users;    
  55. }    
  56. public void setUsers(Set users) {    
  57. this.users = users;    
  58. }    
  59. }    
  60.  而其对应的映射文件如下,首先是User.hbm.xml:    
  61. User.hbm.xml    
  62. <?xml version="1.0"?>    
  63. <!DOCTYPE hibernate-mapping    
  64. PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"    
  65. "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">    
  66.   
  67. <hibernate-mapping>    
  68.   
  69. <class name="onlyfun.caterpillar.User" table="USER">    
  70.   
  71. <id name="id" column="USER_ID" unsaved-value="0">    
  72. <generator class="increment"/>    
  73. </id>    
  74.   
  75. <property name="name">    
  76. <column name="NAME" length="16" not-null="true"/>    
  77. </property>    
  78.   
  79. <many-to-one name="room"    
  80. column="ROOM_ID"    
  81. class="onlyfun.caterpillar.Room"/>    
  82. </class>    
  83.   
  84. </hibernate-mapping>    
  85.  再来是Room.hbm.xml:    
  86. Room.hbm.xml    
  87. <?xml version="1.0"?>    
  88. <!DOCTYPE hibernate-mapping    
  89. PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"    
  90. "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">    
  91.   
  92. <hibernate-mapping>    
  93.   
  94. <class name="onlyfun.caterpillar.Room" table="ROOM">    
  95.   
  96. <id name="id" column="ROOM_ID" unsaved-value="0">    
  97. <generator class="increment"/>    
  98. </id>    
  99.   
  100. <property name="address" type="string"/>    
  101.   
  102. <set name="users" table="USER" cascade="all">    
  103. <key column="ROOM_ID"/>    
  104. <one-to-many class="onlyfun.caterpillar.User"/>    
  105. </set>    
  106. </class>    
  107.   
  108. </hibernate-mapping>    
  109.  这就形成了User与Room之间的双向关联映射,我们可以使用以下的程序进行测试:    
  110. HibernateTest.java    
  111. import onlyfun.caterpillar.*;    
  112. import net.sf.hibernate.*;    
  113. import net.sf.hibernate.cfg.*;    
  114.   
  115. public class HibernateTest {    
  116. public static void main(String[] args) throws HibernateException {    
  117. SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();    
  118.   
  119. Room room = new Room();    
  120. room.setAddress("NTU-M8-419");    
  121.   
  122. User user1 = new User();    
  123. user1.setName("bush");    
  124.   
  125. User user2 = new User();    
  126. user2.setName("bush");    
  127.   
  128. /*   
  129. * 因为没有设定inverser,所以只须从parent维护即可   
  130. */    
  131. //user1.setRoom(room);    
  132. //user2.setRoom(room);    
  133.   
  134. room.getUsers().add(user1);    
  135. room.getUsers().add(user2);    
  136.   
  137. Session session = sessionFactory.openSession();    
  138. Transaction tx= session.beginTransaction();    
  139. session.save(room);    
  140.   
  141. tx.commit();    
  142. session.close();    
  143.   
  144. sessionFactory.close();    
  145. }    
  146. }    
  147.  基本上就数据的储存来说,这样就已经足够,但这样的设计会有效能问题,显然的,这个程序将Room与User之间的关联交由Room来维持,就Room而言,它要先储存自已,然后储存其所包括的多个User,之后再对每一个User更新(update)对自己(Room)的关联,具体而言,这个程序必须实行以下的SQL:    
  148. Hibernate: insert into ROOM (address, ROOM_ID) values (?, ?)    
  149. Hibernate: insert into USER (NAME, ROOM_ID, USER_ID) values (?, ?, ?)    
  150. Hibernate: insert into USER (NAME, ROOM_ID, USER_ID) values (?, ?, ?)    
  151. Hibernate: update USER set ROOM_ID=? where USER_ID=?    
  152. Hibernate: update USER set ROOM_ID=? where USER_ID=?    
  153.  就Room而言,它并不知道其所包括的User是不是一个已储存的对象,或者即使为已储存对象,也不知道USER表格上的ROOM_ID是不是参考至ROOM表格的ROOM_ID上,所以它必须针对自己所包括的User对象一个个进行更新,以确保USER表格上的ROOM_ID是指向自己。    
  154.  如果将关联的维护交给User的话会比较容易,因为每个User都对应至一个Room,在储存时并用像Room一样必须对Set中的每个对象作检查,为了将关联的维护交给User,我们可以在Room.hbm.xml中的<set>修改,加上inverse="true",表示将关联的维护「反过来」交给User作:    
  155. Room.java    
  156. <set name="users" table="USER" inverse="true" cascade="all">    
  157. <key column="ROOM_ID"/>    
  158. <one-to-many class="onlyfun.caterpillar.User"/>    
  159. </set>    
  160.  由于将关联的维护交给User来作了,所以我们必须在储存时,明确的将Room设定给User,也就是说,必须这样作:    
  161. /*   
  162. * 因为有user维护关联,所以必须呼叫setRoom   
  163. */    
  164. user1.setRoom(room);    
  165. user2.setRoom(room);    
  166.   
  167. room.getUsers().add(user1);    
  168. room.getUsers().add(user2);    
  169.  这比不加上inverse="true"设定时多了个指定的动作,您必须多键几个字,所带来的是效率上的增加,Hibernate的持久层管理员会先储存Room,然后储存User,如此就可以省去之前再进行更新的动作,具体来说,就是会执行以下的SQL:    
  170. Hibernate: insert into ROOM (address, ROOM_ID) values (?, ?)    
  171. Hibernate: insert into USER (NAME, ROOM_ID, USER_ID) values (?, ?, ?)    
  172. Hibernate: insert into USER (NAME, ROOM_ID, USER_ID) values (?, ?, ?)    
  173.  与先前不同的是,由于关联交给了User维护,所以这次Room不用一一更新USER以确定每个ROOM_ID都指向自已。    
  174.  如果指定了inverse="true",而不确实的将Room指定给User会如何?那么User与Room会各自储存,但彼此没有关联,也就是User将不会参考至Room,USER表格的ROOM_ID将为null,例如:    
  175. mysql> select * from USER;    
  176. +---------+------+---------+    
  177. | USER_ID | NAME | ROOM_ID |    
  178. +---------+------+---------+    
  179. 1 | bush | NULL |    
  180. +---------+------+---------+    
  181.   
  182. mysql> select * from ROOM;    
  183. +---------+------------+    
  184. | ROOM_ID | address |    
  185. +---------+------------+    
  186. 1 | NTU-M8-419 |    
  187. +---------+------------+    
  188.  作个总结,在设立双向关联时,关联由多对一中「多」的哪一方维护,会比由「一」的哪一方维护来的方便,在Hibernate可以藉由inverse来设定,不设定inverse基本上也可以运行,但是效能会较差。    
  189.  设定了inverse,必须要明确的设定双方的参考,以这个主题的例子,Room要设定给User,而User也要知道Room的存在,这比不设定inverse需要键入较多的字,但从另一方面,比较符 合程序设计的直觉(单看User与Room类别,两者要互相参考时,本来就要明确设定)。    
分享到:
评论
4 楼 franciswang 2009-02-19  
我的配置文件和你的一样,但是为什么还是先存ROOM再存USER然后UPDATE USER的外键。
3 楼 heitianba 2009-02-10  
  
2 楼 tianlwww 2008-12-24  
700多人看,没一个回复的,太让人心寒.............
1 楼 tianlwww 2008-12-24  

相关推荐

    彻底明白Hibernate中的Inverse

    在Hibernate中,`Inverse`是一个重要的概念,它涉及到实体之间的关联管理。本文将深入探讨`Inverse`属性,以及它在Hibernate中的作用和应用场景。 一、Hibernate与对象关系映射 Hibernate通过ORM机制将Java对象与...

    JavaEE学习笔记之Hibernate表关系之一对多(inverse详解)

    1. **关联的插入和更新**:在一对多关系中,如果设置`inverse="true"`,那么在保存或更新父实体时,Hibernate会自动处理与子实体的关联,添加新的子实体或更新已存在的关联。相反,如果在子实体上操作,Hibernate将...

    Hibernate中cascade和inverse应用

    在 Hibernate 框架中,`cascade` 和 `inverse` 是两个重要的概念,它们主要用于管理对象之间的持久化关系,特别是涉及到一对一(one-to-one)、一对多(one-to-many)和多对多(many-to-many)关系时。这两个属性都...

    hibernate 级联(cascade和inverse)一对多

    在Java的持久化框架Hibernate中,级联操作(Cascade)和反转(Inverse)是两个重要的概念,它们主要用于管理对象关系模型中的关联关系。在一对多的关系中,这些特性可以帮助简化数据操作,提高代码的可读性和维护性...

    Hibernate中cascade与inverse属性详解

    在我们的例子中,如果在 `Student` 的映射文件中,将 `class` 的关联设置为 `inverse="true"`,那么在保存学生对象时,Hibernate 不会更新班级表中的关联信息,除非在学生对象中显式设置班级。 总结: `cascade` ...

    inverse=true的总结

    总结,`inverse=true`是Hibernate中管理双向一对多关联的重要属性,它影响了对象与数据库之间的同步策略。理解并正确运用这个特性,有助于我们编写出更加高效、易维护的代码。通过阅读相关博客和源码,我们可以更...

    inverse 例子

    在一对多关系中,如果在多方(ManyToOne)的一端设置了`inverse="true"`,那么Hibernate将不再在多方对象保存或更新时处理关联。相反,它会交给一对一或一对多的那端去处理。这样做可以优化性能,避免不必要的数据库...

    hibernate之一对多配置demo

    【hibernate之一对多配置demo】:在Java开发中,Hibernate是一个强大的对象关系映射(ORM)框架,它简化了数据库与Java对象之间的交互。本教程主要关注Hibernate中的一对多关系配置,并通过XML来实现,同时也涵盖了...

    Hibernate 简单 PPT 总结

    在Hibernate中,`inverse`属性是一个关键的概念,它用于定义一对多或多对一关系中的维护端。`inverse="true"`表示另一端负责维护关联关系,这在处理关联实体的保存和更新时具有重要意义。例如,如果你有一个学生类和...

    hibernate一对多代码

    在Java的持久化框架Hibernate中,"一对多"映射是一种常见的关系模型,它反映了数据库中表之间的关联。本文将详细解析"hibernate一对多映射"的概念、配置及其实现过程,以帮助理解并掌握这一核心特性。 首先,我们要...

    Hibernate(一对多表操作)

    本篇主要讨论的是Hibernate中的一对多关系映射,以及如何在实际操作中进行配置和使用。 一对多关系指的是一个实体可以与多个其他实体相关联。例如,在用户系统中,一个用户可以有多个订单,这就是典型的一对多关系...

    Hibernate电子书(全)

    正确设置`inverse`可以确保Hibernate在处理关联关系时的行为符合预期。 #### 一对一与多对多实体映射 Hibernate支持一对一和多对多关系的映射,分别通过`@OneToOne`和`@ManyToMany`注解实现。这些映射策略使得复杂...

    hibernate单向多对多映射(XML版)

    在Java世界中,Hibernate是一个非常流行的ORM(对象关系映射)框架,它允许开发者将数据库操作转换为面向对象的方式,从而提高开发效率。本主题聚焦于"hibernate单向多对多映射",特别是在XML配置文件中的实现。在这...

    hibernate xml

    在实际开发中,理解和熟练运用Hibernate的XML配置对于提高开发效率和保证数据一致性至关重要。理解`cascade`和`inverse`的概念,能够帮助我们更好地设计对象模型,避免数据同步的问题,同时,灵活运用级联操作可以...

    hibernate自身关联一对多实例(树形结构)

    例如,添加一个新节点到树形结构中,可以先创建父节点和子节点对象,然后设置它们的引用关系,最后将父节点保存到数据库,Hibernate会自动处理关联关系。 ```java ParentEntity parent = new ParentEntity(); List...

    Hibernate持久化映射一对多和多对一

    本文将深入探讨Hibernate中的两个重要概念:一对多(One-to-Many)和多对一(Many-to-One)的持久化映射。 ### 一对多映射 **定义**: 一对多映射表示一个实体(如部门)可以关联多个实体(如员工)。在数据库层面...

    Hibernate开发租房系统2 源码

    描述提到“使用cascade和inverse优化区和街道关联关系”,这意味着我们将深入理解Hibernate的cascade和inverse属性,以及它们在双向一对多关联关系中的应用。 Hibernate是Java领域中广泛使用的对象关系映射(ORM)...

    hibernate bag 集合映射

    在Hibernate中,集合映射是指将数据库中的表与Java集合对象(如List、Set等)进行关联,方便对一组相关数据进行操作。 "bag"是Hibernate中的一种集合类型,表示无序的、可重复的对象集合。在数据库层面,这通常对应...

    Hibernate一对多教学

    本教程主要聚焦于Hibernate中的一对多关系映射,这对于理解复杂的数据库交互至关重要。 一、Hibernate概述 Hibernate是Java中的Object-Relational Mapping(ORM)工具,它将数据库的表映射为Java对象,使得开发人员...

Global site tag (gtag.js) - Google Analytics