6

I'm using Hibernate 3.0 with Java.

I have the following classes.

Teacher.java

private long id;
private String teacherName;
private List<Student> students;
// getter-setter of all

Subject.java

private long id;
private String subjectName;
private List<Student> students;
// getter-setter of all

Student.java

 private long id;
 private String studentName;

// getter-setter of both

Teacher.hbm.xml

<class name="Teacher" table="teacher_master">
    <!--other mappings-->

    <list name="students" cascade="refresh" table="teacher_student_master">
        <key column="teacher_id"/>
        <index column="student_teacher_position" type="integer"/>
        <many-to-many class="Student" column="student_id"/>
    </list>
</class>

Subject.hbm.xml

<class name="Subject" table="subject_master">
    <!--other mappings-->

    <list name="students" cascade="refresh" table="subject_student_master">
        <key column="subject_id"/>
        <index column="student_subject_position" type="integer"/>
        <many-to-many class="Student" column="student_id"/>
    </list>
</class>

Student.hbm.xml contains mappings for id & studentName properties.

Problem I'm facing is:

I delete a row from student_master through Hibernate.

Student stu = new Student();
stu.setId(1l);
session.delete(stu);
transaction.commit();

But the references of the deleted student (id = 1) are not deleted from the tables teacher_student_master and subject_student_master.

How can I overcome this issue?

Note: It would be great if I can overcome this issue by doing some kind of configuration with Hibernate instead of coding & query firing.

Edit: I've seen this link. But in that, it's mentioned that I need to do some coding like, first get all the teachers associated with student=1, then remove the student=1 from the list of student & then update teacher. I want to avoid this coding. Is it possible?

Community
  • 1
  • 1
RAS
  • 8,100
  • 16
  • 64
  • 86

3 Answers3

0

You can use @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) to the columns you want this behavior. See this question for more information.

Or, since you are using Hibernate configuration through XML, use cascade="delete-orphan". Take a look at this blog post where different types of cascades are explained.

Community
  • 1
  • 1
Thiago
  • 883
  • 11
  • 20
  • 2
    @RAS is using XML mapping, not annotations. Its would be better if you provide the answer using HBM mapping only. – Vimal Bera Aug 22 '13 at 13:19
  • I've seen both the links given by you. But in both the links, it's mentioned that I need to do some coding like, first get all the teachers associated with student=1, then remove the student=1 from the list of student & then update teacher. I want to avoid this coding. Is it possible? – RAS Aug 22 '13 at 13:32
  • Well, let's say you have the following tables: Student, Teacher and Course (that links Student and Teacher). By using DELETE_ORPHAN on Student's reference to Course, deleting the student=1 will also delete all Courses that have a relationship to this student. You don't have to fetch all Courses and delete them manually, Hibernate will do that for you. – Thiago Aug 22 '13 at 13:37
  • I don't want to delete Course but to break the link between Student & Course. In the 2nd link, this code block is there: `/*line 1*/ StockDailyRecord sdr1 = (StockDailyRecord)session.get(StockDailyRecord.class, new Integer(56)); /*line 2*/ StockDailyRecord sdr2 = (StockDailyRecord)session.get(StockDailyRecord.class, new Integer(57)); /*line 3*/ Stock stock = (Stock)session.get(Stock.class, new Integer(2)); /*line 4*/ stock.getStockDailyRecords().remove(sdr1); /*line 5*/ stock.getStockDailyRecords().remove(sdr2); /*line 6*/ session.saveOrUpdate(stock);` – RAS Aug 22 '13 at 13:53
  • What I need is the following: `/*line 1*/ StockDailyRecord sdr1 = (StockDailyRecord)session.get(StockDailyRecord.class, new Integer(56)); /*line 2*/ StockDailyRecord sdr2 = (StockDailyRecord)session.get(StockDailyRecord.class, new Integer(57)); /*line 3*/ session.delete(sdr1); /*line 4*/ session.delete(sdr2);` – RAS Aug 22 '13 at 13:54
  • You said you want to break the link between Student & Course, but want to delete a Student that has a Course. That does not make sense, since Course is a relationship of a Student to a Teacher, if you delete a Student there is no meaning in having this relation anymore. I think you must review your table mapping, having in mind that Course is simply a relationship. Also, you have a list of Student in Teacher, that will make Hibernate create a relationship table for you, is that relationship really necessary? – Thiago Aug 22 '13 at 14:24
  • Let me revise the question. I'm deleting Student. At that time, the link between the deleted Student & the Teacher should also get deleted. But Teacher attached to the deleted Student should not be deleted. Are you getting my point? – RAS Aug 22 '13 at 14:39
0

Use cascade="delete" property in both mapping files. It might solve your problem. If you want to assigned "refresh" then assigned multiple properties to cascade using ;.

Vimal Bera
  • 10,346
  • 4
  • 25
  • 47
  • I know about `cascade = delete`. But as per my knowledge it works like, if I delete record of **teacher_master**, it will delete record from **teacher_student_master**. My case is reverse. I'm deleting record from **student_master** & not from **teacher_master**. – RAS Aug 22 '13 at 13:21
0

Hibernate don't delete the rows because the Student class is not aware of the relationships. To do that you should have bi-directional relationships: a @ManyToMany List/Set of Teacher and a @ManyToMany List/Set of Subject in the Student class

Or, at least, a database delete cascade on the foreign key student_id of the tables teacher_student_master and subject_student_master will delete the rows in the database (I think the first solution is better).

But, in any case, you should iterate over the student's subjects and teachers to remove this student, even if the row are deleted in the database, the student object is still there and it could raise some issues in your application... Generally speaking take care of relationships (both side) before saving with Hibernate

With a bidirectional relationship it's easier

for(Teacher teacher: student.teachers) {
    teacher.remove(student);
}

for(Subject subject: student.subjects) {
    subject.remove(student);
}
kwisatz
  • 1,266
  • 3
  • 16
  • 36