Hibernate –カスケードの例(保存、更新、削除、削除オーファン)
カスケードは、反対側の状態を手動で管理するために必要なコード行を保存する便利な機能です。
コレクションの状態を自動的に管理するために、「マッピング」キーワードがコレクションマッピングに表示されることがよくあります。 このチュートリアルでは、このone-to-many exampleを使用してカスケード効果を示します。
カスケード保存/更新の例
この例では、「Stock」が保存されている場合、参照されているすべての「stockDailyRecords」もデータベースに保存する必要があります。
1. 更新の保存カスケードなし
previous sectionで、「Stock」とその参照される「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 example.stock (STOCK_CODE, STOCK_NAME) values (?, ?) Hibernate: insert into example.stock_daily_record (STOCK_ID, PRICE_OPEN, PRICE_CLOSE, PRICE_CHANGE, VOLUME, DATE) values (?, ?, ?, ?, ?, ?)
2. 更新保存カスケード
cascade=”save-update”は、「stockDailyRecords」で宣言され、保存と更新のカスケード効果を有効にします。
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 example.stock (STOCK_CODE, STOCK_NAME) values (?, ?) Hibernate: insert into example.stock_daily_record (STOCK_ID, PRICE_OPEN, PRICE_CLOSE, PRICE_CHANGE, VOLUME, DATE) values (?, ?, ?, ?, ?, ?)
コードsession.save(stockDailyRecords);は不要になりました。「Stock」を保存すると、参照されている「stockDailyRecords」に保存操作が「カスケード」され、両方がデータベースに自動的に保存されます。
カスケード削除の例
この例では、「Stock」が削除された場合、参照されている「stockDailyRecords」もすべてデータベースから削除する必要があります。
1. 削除カスケードなし
すべての「stockDailyRecords」をループして、1つずつ削除する必要があります。
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 example.stock_daily_record where DAILY_RECORD_ID=? Hibernate: delete from example.stock where STOCK_ID=?
2. カスケード削除
cascade=”delete”は、カスケード削除効果を有効にするために「stockDailyRecords」で宣言されています。 「Stock」を削除すると、その参照「stockDailyRecords」はすべて自動的に削除されます。
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 example.stock_daily_record where DAILY_RECORD_ID=? Hibernate: delete from example.stock where STOCK_ID=?
カスケード削除オーファンの例
上記のカスケード削除オプションでは、Stockを削除すると、その参照されているすべての「stockDailyRecords」もデータベースから削除されます。 参照されている2つの「stockDailyRecords」レコードだけを削除する場合はどうでしょうか。 これは孤立した削除と呼ばれます。例を参照してください…
1. 削除オーファンカスケードなし
「stockDailyRecords」を1つずつ削除する必要があります。
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 example.stock_daily_record where DAILY_RECORD_ID=? Hibernate: delete from example.stock_daily_record where DAILY_RECORD_ID=?
2. 孤立したカスケードの削除
cascade=”delete-orphan”は、「stockDailyRecords」で宣言され、孤立したカスケードの削除効果を有効にします。 ストックを保存または更新すると、既に削除済みとしてマークされている「stockDailyRecords」が削除されます。
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 example.stock_daily_record where DAILY_RECORD_ID=? Hibernate: delete from example.stock_daily_record where DAILY_RECORD_ID=?
要するに、delete-orphanを使用すると、親テーブルは子テーブル内のいくつかのレコードを削除(孤立した削除)できます。
カスケードを有効にする方法は?
カスケードは、XMLマッピングファイルと注釈の両方でサポートされています。
1. XMLマッピングファイル
XMLマッピングファイルで、関係変数でcascadeキーワードを宣言しました。
2. アノテーション
アノテーションで、@ CascadeアノテーションでCascadeType.SAVE_UPDATE(保存、更新)とCascadeType.REMOVE(削除)を宣言しました。
//Stock.java @OneToMany(mappedBy = "stock") @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE}) public SetgetStockDailyRecords() { return this.stockDailyRecords; }
逆対カスケード
どちらもまったく異なる概念です。differential hereを参照してください。
結論
カスケードは、相手側の状態を自動的に管理するための非常に便利な機能です。 ただし、この機能には価格があります。賢く使用しないと(更新または削除)、パフォーマンスを低下させるために多くの不要なカスケード効果(カスケード更新)が生成されたり、使用しなかったデータを削除(カスケード削除)したりします期待した。