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

标签: 实例 解释 inverse | 发表时间:2013-09-25 18:30 | 作者:
出处:http://www.iteye.com
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 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [实例 解释 inverse] 推荐:

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

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

Hibernate中inverse="true"的理解

- - 企业架构 - ITeye博客
转自: http://lijiejava.iteye.com/blog/776587. 即Customer类具有一个set集合属性orders,其中Order是一个普通的类: . t_customer:  两个字段:id  name  . t_order:     三个字段:id  orderName  customerid  .

Oracle实例与数据库的概念详细解释

- - CSDN博客数据库推荐文章
刚接触ORACLE的人肯定会对实例和数据库感到困惑,实例到底代表些什么. ORACLE实例 = 进程 + 进程所使用的内存(SGA)实例是一个临时性的东西,你也可以认为它代表了数据库某一时刻的状态. 数据库 = 重做文件 + 控制文件 + 数据文件 + 临时文件. 数据库是永久的,是一个文件的集合.

求解释

- 月七 - FeedzShare
来自: 水木社区 Joke/笑话连篇 保留区 - FeedzShare  . 发布时间:2011年09月27日,  已有 2 人推荐. 发信人: yutourr (倪趣,你回来), 信区: Joke. 发信站: 水木社区 (Tue Sep 27 15:30:28 2011), 站内. 三个中微子走进了酒馆,酒保问:“你们每个都需要一杯酒吗.

解释器Interpreter

- - 企业架构 - ITeye博客
所谓解释器模式就是定义一个语言的文法,并建立一个解释器来解释该语言中的句子. 比如:taglib标签,正则表达式都是采用的解释器. 解释器不仅仅只定义一种语法语义,更可以使用一个抽象语法树定义一个语言实例.     AbstractExpression: 抽象表达式. 声明一个抽象的解释操作,该接口为抽象语法树中所有的节点共享.

/b/ 解释圣经

- chengdujin - hUrR DuRr

你们懂的……不解释

- 俊峰 - 工口堂
magnet:?xt=urn:btih:HGIXQBQZJK5N2FNA4GBYNHXPSIW6CTOJ分类: 小卖部 | 评论数: 0.

[原]Dubbo实例

- -
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. Remoting: 网络通信框架,实现了sync-over-async 和 request-response 消息机制. RPC: 一个远程过程调用的抽象,支持负载均衡、容灾和集群功能. Registry: 服务目录框架用于服务的注册和服务事件发布和订阅.

VisualVM 使用实例

- - 开源软件 - ITeye博客
VisualVM 是一款免费的性能分析工具. 监控程序运行的实时数据,从而进行动态的性能分析. 同时,它能自动选择更快更轻量级的技术尽量减少性能分析对应用程序造成的影响,提高性能分析的精度. 转储:性能分析工具从内存中获得当前状态数据并存储到文件用于静态的性能分析. 1     系统转储:JVM 生成的本地系统的转储,又称作核心转储.

学习AngularJS实例

- - Web前端 - ITeye博客
怎么样快速学习AngularJS. 相信很多初学者都有过或者类似的疑问,其实这个问题没有标准的答案,每个人的技术背景、工作经验等等都不经相同,所以学习AngularJS的切入点肯定也就不同,我之前初略使用过knockoutjs,当我第一眼看到AngularJS的Helloworld案例后,顿时就被声明式的语法和强大的双向绑定特性所吸引.