用实例来解释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);


[b][color=darkred]那么Hibernate会更新表StockDailyRecord的列“stock_daily_record.ITEM_ID”的值吗?[/color][/b]

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表示这一方不是关系的拥有者,不负责维护关系的更新。

参考文章
[url]http://www.developer.am/documentation/hibernate/?page=inverse_true__explanation[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值