Hibernate – カスケードの例(保存、更新、削除、削除 – 孤立)
Cascade is a convenient feature to save the lines of code needed to
manage the state of the other side manually.
コレクションの状態を自動的に管理するために、「カスケード」キーワードがコレクションマッピングに表示されることがよくあります。このチュートリアルでは、このリンク://hibernate/hibernate-one-to-many-relationship-example/[1対多の例]を使用してカスケード効果を実演します。
カスケードセーブ/アップデートの例
この例では、 ‘Stock’が保存されている場合、参照されている ‘stockDailyRecords’もすべてデータベースに保存する必要があります。
1.セーブアップデートカスケードなし
リンク://hibernate/hibernate-one-to-many-relationship-example/[前のセクション]では、 ‘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 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. 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); ** コードは不要です。 ‘Stock’を保存するときは、保存操作を ‘stockDailyRecords’という名前で “カスケード”し、データベースに自動的に保存します。
カスケード削除の例
この例では、 ‘Stock’が削除された場合、参照されている ‘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.カスケードを削除する
-
cascade = “delete” ** は ‘stockDailyRecords’で宣言され、削除カスケード効果を有効にします。 ‘Stock’を削除すると、そのすべての参照 ‘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=?
カスケードdelete-orphanの例
上記カスケード削除オプションでは、ストックを削除すると、参照されている ‘stockDailyRecords’もデータベースから削除されます。
2つの参照された ‘stockDailyRecords’レコードを削除したい場合はどうですか?これは孤立した削除と呼ばれ、例を参照してください…
1. delete-orphanカスケードはありません
‘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 mkyong.stock__daily__record where DAILY__RECORD__ID=? Hibernate: delete from mkyong.stock__daily__record where DAILY__RECORD__ID=?
2. delete-orphanカスケード
-
cascade = “delete-orphan” ** は ‘stockDailyRecords’で宣言され、孤立カスケード効果の削除を有効にします。ストックを保存または更新すると、すでに削除されたマークの「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=?
In short, delete-orphan allow parent table to delete few records (delete
orphan) in its child table.
カスケードを有効にする方法は?
カスケードは、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.注釈
アノテーションでは、@カスケードアノテーションの
CascadeType.SAVE__UPDATE
(save、update)と
CascadeType.REMOVE
(delete)を宣言しました。
//Stock.java @OneToMany(mappedBy = "stock") @Cascade({CascadeType.SAVE__UPDATE, CascadeType.DELETE}) public Set<StockDailyRecord> getStockDailyRecords() { return this.stockDailyRecords; }
さらなる研究 – リンク://hibernate/cascade-jpa-hibernate-annotation-common-mistake/[カスケード – JPAとハイバーネーション注釈のよくある間違い]
逆数対カスケード
両方ともまったく異なる概念です。リンク://hibernate/different-between-cascade-and-inverse/[差分はこちら]を参照してください。