级联是一项方便的功能,用于保存手动管理另一侧状态所需的代码行。
“ Cascade”关键字通常出现在集合映射上,以自动管理集合的状态。 在本教程中,此一对多示例将用于演示级联效果。
级联保存/更新示例
在此示例中,如果保存了“库存”,则其所有引用的“ stockDailyRecords”也应保存到数据库中。
1.没有保存更新级联
在上一节中 ,如果要将“股票”及其引用的“ 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.使用保存更新级联
在“ stockDailyRecords ”中声明了层叠=“保存更新”以启用保存更新层叠效果。
<!-- 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”也应从数据库中删除。
1.没有删除级联
您需要循环所有“ 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 ”中声明了级联=“删除”以启用删除级联效果。 当您删除“股票”时,其所有参考“ 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=?
级联删除孤儿示例
在上述层叠删除选项中,如果删除Stock,则其所有引用的“ stockDailyRecords”也将从数据库中删除。 如果您只想删除两个引用的“ stockDailyRecords”记录怎么办? 这称为孤立删除,请参见示例…
1.没有删除孤立级联
您需要一个一个地删除“ 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.使用delete-orphan级联
在“ 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=?
简而言之,delete-orphan允许父表删除其子表中的几个记录(删除孤子)。
如何启用级联?
XML映射文件和注释均支持级联。
1. 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>
2.注释
在注释中,在@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注释常见错误 。
逆与级联
结论
级联是非常方便的功能,可以自动管理另一侧的状态。 但是,此功能带有价格,如果您不明智地使用它(更新或删除),它将生成许多不必要的级联效果(级联更新)以降低性能,或删除(级联删除)一些您没有使用的数据预期。
翻译自: https://mkyong.com/hibernate/hibernate-cascade-example-save-update-delete-and-delete-orphan/