`
darrenzhu
  • 浏览: 804249 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

用实例来解释inverse=true的含义

阅读更多
inverse=true含义:
关系(Relationship)由两方组成,其中被定义了inverse=true的一方表示:“我是反向被控制的一方,我不负责维护关系”,而inverse=false则表示:"我是关系的控制方,拥有者,我会维护关系"。默认情况为inverse=false,即关系的两方都维护和控制关系,这种情况会造成一方重复一遍另一方已经完成的事情,比如更新外键列的值,这是不可取的,需要使用inverse=true来避免。


案例解释
1.类定义
Stock.java
public class Stock implements java.io.Serializable
   ...
   private Set<StockDailyRecord> stockDailyRecords = 
                                  new HashSet<StockDailyRecord>(0);
   ...

StockDailyRecord.java
public class StockDailyRecord implements java.io.Serializable
   ...
   private Stock stock;
   ...


2. hibernate配置
Stock.hbm.xml
<hibernate-mapping>
    <class name="com.developer.ammon.Stock" table="stock" ...>
    ...
    <set name="stockDailyRecords" table="stock_daily_record" fetch="select">
        <key>
            <column name="STOCK_ID" not-null="true" />
        </key>
        <one-to-many class="com.developer.ammon.StockDailyRecord" />
    </set>
    ...

StockDailyRecord.hbm.xml
<hibernate-mapping>
  <class name="com.developer.ammon.StockDailyRecord" table="stock_daily_record" ...>
  ...
  <many-to-one name="stock" class="com.developer.ammon.Stock">
       <column name="STOCK_ID" not-null="true" />
  </many-to-one>
  ...



3. 问题
看如下文件 – “Stock.hbm.xml“.
<hibernate-mapping>
    <class name="com.developer.ammon.Stock" table="stock" ...>
    ...
    <set name="stockDailyRecords" table="stock_daily_record" fetch="select">
        <key>
            <column name="STOCK_ID" not-null="true" />
        </key>
        <one-to-many class="com.developer.ammon.StockDailyRecord" />
    </set>
    ...

如果修改Stock对象的stockDailyRecords变量,然后保存Stock对象,代码如下:
Stock stock = new Stock();
stock.getStockDailyRecords().add(stockDailyRecords);
session.save(stock);


那么Hibernate会更新表StockDailyRecord的列“stock_daily_record.ITEM_ID”的值吗?

Hibernate: 
    update developer.stock_daily_record 
    set STOCK_ID=? 
    where DAILY_RECORD_ID=?


4. 答案
"inverse" 的值决定了上面的update语句会不会产生和执行
Inverse = false (如果不显示设置,默认值就是false) – 会执行更新(所以默认是会更新)
Inverse = true – 不会.


"Inverse = false" 例子
<!--Stock.hbm.xml-->
<set name="stockDailyRecords" table="stock_daily_record" ...>

如果不显示设置inverse的值,inverse默认值就是false,那么上面的xml片段等价于如下片段

<!--Stock.hbm.xml-->
<set name="stockDailyRecords" inverse="false" table="stock_daily_record" ...>

这意味着,关系的两方都是关系的拥有者。在Hibernate里,这会导致两方都会更新“StockDailyRecord”表的外键“stock_daily_record.ITEM_ID”的值:


如果Stock类的集合变量(stockDailyRecords)被修改了,Stock会更新外键“stock_daily_record.ITEM_ID”的值;
如果StockDailyRecord类的Stock变量被修改了,StockDailyRecord也会更新外键“stock_daily_record.ITEM_ID”的值;


1) Insert example
下面是当inverse=false时的保存新Stock对象的例子,Hibernate会产生2条SQL语句,一条insert,一条update

Stock stock = new Stock();
stock.getStockDailyRecords().add(stockDailyRecords);
session.save(stock);
Output

Hibernate: 
    insert into developer.stock (STOCK_CODE, STOCK_NAME) 
    values (?, ?)
...
Hibernate: 
    update developer.stock_daily_record 
    set STOCK_ID=? 
    where DAILY_RECORD_ID=?


由于Stock是关系的拥有者(inverse=false),Stock会更新列“stock_daily_record.ITEM_ID”的值因为集合变量(stockDailyRecords)有修改

2) Update example
下面是当inverse=false时的update已经持久化过了的Stock对象的例子,Hibernate会产生3条SQL语句,一条insert,2条update
        Query q = session.createQuery("from Stock where stockCode = :stockCode ");
        q.setParameter("stockCode", "4715");
        Stock stock = (Stock)q.list().get(0);
        stock.setStockName("GENM1");
 
        StockDailyRecord stockDailyRecords = new StockDailyRecord();
        //set stockDailyRecords data
 
        stockDailyRecords.setStock(stock);        
        stock.getStockDailyRecords().add(stockDailyRecords);
 
        session.save(stockDailyRecords);
        session.update(stock);
Output

Hibernate: 
    insert into developer.stock_daily_record (STOCK_ID, ...) 
    values (?, ...)
 
Hibernate: 
    update developer.stock 
    set STOCK_CODE=?, STOCK_NAME=? 
    where STOCK_ID=?
 
Hibernate: 
    update developer.stock_daily_record 
    set STOCK_ID=? 
    where DAILY_RECORD_ID=?

由于Stock是关系的拥有者(inverse=false),Stock会更新列“stock_daily_record.ITEM_ID”的值因为集合变量(stockDailyRecords)有修改

但是,第3条SQL语句是必须的,显而易见,第1条insert语句就已经为developer.stock_daily_record 保存了合适的STOCK_ID,所以第3条update语句是没有意义的,而且会损失性能。
通过设置inverse=true,我们可以阻止Hibernate产生第3条不必要的update语句


inverse = “true” 案例
<!--Stock.hbm.xml-->
<set name="stockDailyRecords" inverse="true" table="stock_daily_record" ...>

集合变量stockDailyRecords上的inverse=true声明表示Stock不是关系的拥有者,关系由StockDailyRecord来维护。 在Hibernate里,这会阻止Stock更新外键“stock_daily_record.ITEM_ID”的值当集合变量(stockDailyRecords)被修改时。只有StockDailyRecord会更新“stock_daily_record.ITEM_ID”的值当StockDailyRecord的Stock属性被修改时。


1. Insert example
下面是当inverse=true时的保存新Stock对象的例子,Hibernate只会产生一条insert语句
Stock stock = new Stock();
stock.getStockDailyRecords().add(stockDailyRecords);
session.save(stock);
Output

Hibernate: 
    insert into developer.stock (STOCK_CODE, STOCK_NAME) 
    values (?, ?)


由于Stock不是关系的拥有者,所以Stock不会更新表StockDailyRecord列“stock_daily_record.ITEM_ID”的值

2. Update example
Here’s an update example for inverse=”true”, Hibernate will generated two SQL statements, one insert and one update.
下面是当inverse=true时,Hibernate update已经持久化过了的Stock对象的例子,Hibernate会产生2条SQL语句,一条insert,1条update
        Query q = session.createQuery("from Stock where stockCode = :stockCode ");
        q.setParameter("stockCode", "4715");
        Stock stock = (Stock)q.list().get(0);
        stock.setStockName("GENM1");
 
        StockDailyRecord stockDailyRecords = new StockDailyRecord();
        //set stockDailyRecords data
 
        stockDailyRecords.setStock(stock);        
        stock.getStockDailyRecords().add(stockDailyRecords);
 
        session.save(stockDailyRecords);
        session.update(stock);
Output

Hibernate: 
    insert into developer.stock_daily_record (STOCK_ID, ...) 
    values (?, ...)
 
Hibernate: 
    update developer.stock 
    set STOCK_CODE=?, STOCK_NAME=? 
    where STOCK_ID=?


由于Stock不是关系的拥有者,所以Stock不会更新表StockDailyRecord列“stock_daily_record.ITEM_ID”的值


结论
理解inverse的含义对于优化Hibernate的性能是至关重要的,正确的使用会避免Hibernate产生许多不必要的update语句。最后,记住inverse=true表示这一方不是关系的拥有者,不负责维护关系的更新。

参考文章
http://www.developer.am/documentation/hibernate/?page=inverse_true__explanation
0
1
分享到:
评论

相关推荐

    Hibernate级联操作.docx

    Hibernate 是一个流行的对象关系映射(ORM)框架,它允许开发者使用 Java 对象来操作数据库。在 Hibernate 中,级联操作(Cascade)和反向属性(Inverse)是管理对象关系的重要概念,特别是在处理一对多(One-to-...

    Hibernate的多对一和一对多操作实例

    本示例中,我们将使用两个表:`CUSTOMER`和`ORDERS`,来演示“一对多”关系。其中,`CUSTOMER`表包含客户的基本信息,如`id`、`name`和`age`等字段,而`ORDERS`表则存储了订单信息,包括`id`、`CUSTOMER_id`、`ORDER...

    Nhibernate 隐射实例

    它允许开发人员使用面向对象的编程模型来操作数据库,而无需直接编写SQL语句。在这个实例中,我们将深入探讨Nhibernate在处理四种主要关系映射——一对一、一对多、多对一和多对多的关系映射。 ### 一对一关系...

    Hibernate 多表映射关系配置

    &lt;set name="roles" table="user_roles" inverse="true" lazy="true"&gt; &lt;key column="user_id" /&gt; &lt;many-to-many class="com.bean.manytomany.Role" column="role_id" /&gt; ``` `Role.hbm.xml` 示例: ```xml ...

    NHibernate三种关系配置示例

    在上述配置中,我们可以使用 `lazy="true"` 参数来启用懒加载,例如: ```xml &lt;one-to-many name="Employees" lazy="true"/&gt; ``` 总结,NHibernate 通过配置文件或注解支持多种关系映射,包括一对一、一对多和多对...

    Hibernate Mapping Many-to-One 实例 内附源代码及附件下载

    在Java世界中,Hibernate是一个非常流行的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者可以使用面向对象的方式来处理数据。本实例将详细讲解如何在Hibernate中实现Many-to-One关系映射,这是一种常见的...

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

    然后,使用Hibernate的注解来声明这些关联,如`@OneToMany`和`@ManyToOne`。 在配置文件中,我们还需要为这个关联定义映射规则,包括fetch策略(选择是懒加载还是立即加载子项)、级联操作(如删除时是否一同删除...

    hibernate双向一对多关联映射(XML)

    在`&lt;class&gt;`标签内,通过`&lt;set&gt;`标签来定义这个集合,其中`name`属性是Java中的字段名,`table`属性指定数据库中的表名,`inverse="true"`表示这个关联的维护由`Order`端负责: ```xml &lt;set name="orders" table=...

    hibernate的联合主键怎么设置

    如果 Student 的 `inverse="true"`,那么添加一个新的 Student 时,Hibernate 不会在 TeacherStudent 表中插入新的记录。只有在处理 Teacher 时,Hibernate 才会更新中间表。 - 如果两端都是 `inverse="true"`,则...

    hibernate学习5之one-to-many双向关联.docx

    在这个场景中,"一"端通常指的是一个实体可以拥有多个另一个实体的实例,而"多"端则相反,一个实体可以被多个另一个实体实例所拥有。在本例中,我们讨论的是`Student`(学生)和`Classes`(班级)的关系,一个班级...

    Hiberbate 3延迟加载(Lazy)介绍

    &lt;set name="addresses" table="address" lazy="true" inverse="true"&gt; ``` #### 四、延迟加载的实例分析 假设我们有用户(User)和地址(Address)两个实体,一个用户可能有多个地址。如果我们没有使用延迟加载,...

    Hibernate一对多关系的处理.doc

    &lt;set name="computers" inverse="true" lazy="true" cascade="save-update"&gt; &lt;key column="p_id"/&gt; &lt;one-to-many class="Computer"/&gt; &lt;class name="Computer" table="Computer"&gt; &lt;id name="id"&gt; ...

    hibernate学习笔记

    例如,在一对多关系中,如果`inverse`属性被设置为`true`,那么这一方将不会主动触发对关联实体的更新或删除操作,而是依赖于另一方实体来执行这些操作。这有助于避免并发修改异常,同时简化了代码的复杂度。 #### ...

    hibernate的多对多配置

    &lt;set name="courses" table="student_course" inverse="true" cascade="all"&gt; &lt;key column="student_id"/&gt; &lt;many-to-many column="course_id" class="com.example.Course"/&gt; &lt;!-- Course.hbm.xml --&gt; ...

    3.Hibernate 03 表关系详细教案1

    总结,本教程详细介绍了Hibernate中表关系的映射,包括不同关系的配置、`Cascade`和`Inverse`属性的使用,以及如何在Java类和XML配置文件中实现这些映射。理解并掌握这些概念对于高效使用Hibernate进行数据库操作至...

    hql详细讲解,实例演示

    在`Classes`类的映射中,`&lt;set&gt;`标签表示一个班级可以包含多个学生,`inverse="true"`表明学生端维护班级关系,`cascade="all"`表示对集合中的每个实体执行级联操作。`&lt;key&gt;`定义了外键,`&lt;one-to-many&gt;`指定了与之...

    IBaitsNet的对象关系一对多实现

    总结来说,“IBaitsNet的对象关系一对多实现”涉及到的主要知识点包括:对象关系映射(ORM)、一对多关系、映射文件配置、集合属性的使用、外键和主键的概念、以及如何在代码中操作这些关系。通过理解并熟练运用这些...

    角色(使用hibernate映射多对多的关系).zip

    "角色(使用hibernate映射多对多的关系).zip"这个压缩包文件提供了一个实例,展示了如何利用Hibernate来映射数据库中的多对多关联。在这个案例中,"角色"可能是一个典型的业务对象,它可能与多个其他实体有关系,...

    hibernate配置要点详谈

    - 多方设置`inverse=true`,即将主控权交给多方,这样多方可以主动从一方获取外键,然后一次`insert`即可完成。 #### 七、集合类型 - 支持`java.util.Set` 或 `net.sf.hibernate.collection.Bag` 类型的集合。 #...

Global site tag (gtag.js) - Google Analytics