猿教程 Logo

Hibernate级联操作:save, update, delete and delete-orphan

“级联”关键字通常出现在集合映射上,以自动管理集合的状态。 在本教程中,此一对多示例将用于演示级联效应。


级联保存/更新示例

在这个例子中,如果“库存”被保存,所有引用的“stockDailyRecords”也应该保存到数据库中。


没有保存更新级联

在上一节中,如果要将“库存”及其引用的“StockDailyRecord”保存到数据库中,则需要单独保存。

Stock stock = new Stock();
StockDailyRecord stockDailyRecords = new StockDailyRecord();
//set the stock and stockDailyRecords  data

stockDailyRecords.setStock(stock);        
stock.getStockDailyRecords().add(stockDailyRecords);

session.save(stock);
session.save(stockDailyRecords);

产量

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

Hibernate: 
    insert into mkyong.stock_daily_record
    (STOCK_ID, PRICE_OPEN, PRICE_CLOSE, PRICE_CHANGE, VOLUME, DATE) 
    values (?, ?, ?, ?, ?, ?)

2.保存更新级联

“库存日记”中声明了cascade =“save-update”以启用保存更新级联效果。

<!-- Stock.hbm.xml -->
<set name="stockDailyRecords" cascade="save-update" table="stock_daily_record"...>
      <key>
            <column name="STOCK_ID" not-null="true" />
      </key>
      <one-to-many class="com.mkyong.common.StockDailyRecord" />
</set>
Stock stock = new Stock();
StockDailyRecord stockDailyRecords = new StockDailyRecord();
//set the stock and stockDailyRecords  data

stockDailyRecords.setStock(stock);        
stock.getStockDailyRecords().add(stockDailyRecords);

session.save(stock);

产量

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

Hibernate: 
    insert into mkyong.stock_daily_record
    (STOCK_ID, PRICE_OPEN, PRICE_CLOSE, PRICE_CHANGE, VOLUME, DATE) 
    values (?, ?, ?, ?, ?, ?)

代码session.save(stockDailyRecords); 不再需要,当您保存“库存”时,它会将保存操作“级联”为“stockDailyRecords”并将其自动保存到数据库中。


级联删除示例

在这个例子中,如果“库存”被删除,所有引用的“stockDailyRecords”也应该从数据库中删除。


没有删除级联

你需要循环所有的'stockDailyRecords'并逐个删除它。

Query q = session.createQuery("from Stock where stockCode = :stockCode ");
q.setParameter("stockCode", "4715");
Stock stock = (Stock)q.list().get(0);
    
for (StockDailyRecord sdr : stock.getStockDailyRecords()){
         session.delete(sdr);
}
 session.delete(stock);

产量

Hibernate: 
    delete from mkyong.stock_daily_record 
    where DAILY_RECORD_ID=?

Hibernate: 
    delete from mkyong.stock 
    where STOCK_ID=?

2.删除级联

在“stockDailyRecords”中声明了cascade =“delete”以启用删除级联效应。 当您删除“库存”时,其所有引用“stockDailyRecords”将被自动删除。

<!-- Stock.hbm.xml -->
<set name="stockDailyRecords" cascade="delete" table="stock_daily_record" ...>
      <key>
            <column name="STOCK_ID" not-null="true" />
      </key>
      <one-to-many class="com.mkyong.common.StockDailyRecord" />
</set>
Query q = session.createQuery("from Stock where stockCode = :stockCode ");
q.setParameter("stockCode", "4715");
Stock stock = (Stock)q.list().get(0);
session.delete(stock);

产量

Hibernate: 
    delete from mkyong.stock_daily_record 
    where DAILY_RECORD_ID=?

Hibernate: 
    delete from mkyong.stock 
    where STOCK_ID=?

级联删除 - 孤儿示例

在上述级联删除选项中,如果您删除库存,则所有引用的“stockDailyRecords”也将从数据库中删除。 如果你只想删除两个引用的“stockDailyRecords”记录呢? 这被称为孤儿删除,见例子...


没有删除孤儿级联

您需要逐个删除'stockDailyRecords'。

StockDailyRecord sdr1 = (StockDailyRecord)session.get(StockDailyRecord.class, 
                                            new Integer(56));
StockDailyRecord sdr2 = (StockDailyRecord)session.get(StockDailyRecord.class, 
                                            new Integer(57));

session.delete(sdr1);
session.delete(sdr2);

产量

Hibernate: 
    delete from mkyong.stock_daily_record 
    where DAILY_RECORD_ID=?
Hibernate: 
    delete from mkyong.stock_daily_record 
    where DAILY_RECORD_ID=?

2.删除孤立级联

在“stockDailyRecords”中声明cascade =“delete-orphan”以启用删除孤立级联效应。 保存或更新库存时,将删除已经标记为已删除的“stockDailyRecords”。

<!-- Stock.hbm.xml -->
<set name="stockDailyRecords" cascade="delete-orphan" table="stock_daily_record" >
      <key>
            <column name="STOCK_ID" not-null="true" />
      </key>
      <one-to-many class="com.mkyong.common.StockDailyRecord" />
</set>
StockDailyRecord sdr1 = (StockDailyRecord)session.get(StockDailyRecord.class, 
                                       new Integer(56));
StockDailyRecord sdr2 = (StockDailyRecord)session.get(StockDailyRecord.class, 
                                       new Integer(57));

Stock stock = (Stock)session.get(Stock.class, new Integer(2));
stock.getStockDailyRecords().remove(sdr1);
stock.getStockDailyRecords().remove(sdr2);
		
session.saveOrUpdate(stock);

产量

Hibernate: 
    delete from mkyong.stock_daily_record 
    where DAILY_RECORD_ID=?
Hibernate: 
    delete from mkyong.stock_daily_record 
    where DAILY_RECORD_ID=?

如何启用级联?

XML映射文件和注释都支持级联。


XML映射文件

在XML映射文件中,在关系变量中声明了cascade关键字。

<!-- Stock.hbm.xml -->
<set name="stockDailyRecords" cascade="save-update, delete" 
        table="stock_daily_record" ...>
      <key>
            <column name="STOCK_ID" not-null="true" />
      </key>
      <one-to-many class="com.mkyong.common.StockDailyRecord" />
</set>

注释

在注释中,在@Cascade注释中声明了CascadeType.SAVE_UPDATE(保存,更新)和CascadeType.REMOVE(删除)。

//Stock.java
        @OneToMany(mappedBy = "stock")
        @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
	public Set<StockDailyRecord> getStockDailyRecords() {
		return this.stockDailyRecords;
	}

进一步研究 - 级联 - JPA和Hibernate注释常见错误。


反对级联

两者都是完全不同的概念,请看这里的差异。


结论

级联是一个非常方便的功能,可以自动管理对方的状态。 但是,如果您不明智地(更新或删除)使用此功能,则会产生许多不必要的级联效应(级联更新),以降低性能,或删除(级联删除)您没有的数据 预期。


版权声明:本站所有教程均为本站原创或翻译,转载请注明出处,请尊重他人劳动果实。请记住本站地址:www.yuanjiaocheng.net (猿教程) 作者:卿文刚
本文标题: C#环境
本文地址:http://www.yuanjiaocheng.net/Hibernate/cascade-example-save-update.html