続いて、DELETEをやります。
まず、今回のサンプルのおさらいをしておきます。
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されるだけです。