Hibernateをいじる(7)

続いて、DELETEをやります。

まず、今回のサンプルのおさらいをしておきます。

Hibernateをいじる(2)

Study(履修)は、Student(学生)とSubject(科目)のそれぞれを1つ持ち(Studyから見てmany-to-one)、Report(レポート)とExamination(試験)のそれぞれを複数持ちます(Studyから見てone-to-many)。

1.単純にdelete()を使う

//まず削除したいオブジェクトを取得。
Query query = session.createQuery("FROM Study AS study WHERE study.student.gakusekiNo=~ AND study.subject.code=~");
query.setString(0, "0499001");
query.setString(1, "14501");
Study study = (Study)query.uniqueResult();

//いざ削除。
session.delete(study);

簡単ですね。

今回のサンプルでは、Study.hbm.xmlで、ReportとExaminationに対してcascade=”all”が指定されています。

そのため、削除したStudyの配下にあるReportとExaminationはDBから削除されます。

もし、cascade=”none”で、DBで参照制約をかけていると、当然にエラーになります。この辺は、Hibernateだからどうこう…ではないようです。

例をもう1つ。

Study study = (Study)query.uniqueResult();

//2つ目を削除
Report report = (Report)study.getReports().get(1);

//リストから消して…
study.getReports().remove(report);

//子をDELETE
session.delete(report);

このように、親子関係のある子だけを削除する場合、先に親が持つ子のリストから、削除したい子を消しておく必要があります。

いきなり、子だけのsession.delete()をやってしまうと、エラーになります。

2.delete()を使わなくても削除できるケース

どんなケースかというと、親が持つ子のリストから、子を消して、親をupdate()するケースです。

実例を見ましょう。

Study study = (Study)query.uniqueResult();

//2つ目を削除
Report report = (Report)study.getReports().get(1);

//リストから消して…
study.getReports().remove(report);

//親をUPDATE
session.saveOrUpdate(study);

親であるstudyが持つ子のリスト(getReports()で取れるList)から、子のreportをremove()して、親のstudyをsaveOrUpdate()しています。

そうすると、リストから削除された子が消えます。

但し、要注意点が1つ。

このようなプログラムで、期待する挙動(リストから削除した子オブジェクトがDBからもDELETEされている)にするためには、Study.hbm.xmlで、cascade=”all-delete-orphan”にしなくてはなりません。

そのように設定しなければ、子オブジェクトはDBに残り、その外部KEYカラムがnullとしてUPDATEされるだけです。

この記事を書いた人

井上 研一

株式会社ビビンコ代表取締役、ITエンジニア/経済産業省推進資格ITコーディネータ。AI・IoTに強いITコーディネータとして活動。画像認識モデルを活用したアプリや、生成AIを業務に組み込むためのサービス「Gen2Go」の開発などを行っている。近著に「使ってわかった AWSのAI」、「ワトソンで体感する人工知能」。日本全国でセミナー・研修講師としての登壇も多数。