Hi,
I am having a Hibernate For Dummies problem with a parent -> child relationship deleting the children when I delete the parent. My understanding is that if I specify cascade="all-delete-orphan" that dereferenced children will be deleted. But, I assume that if I delete the parent entity via a call to session.delete(parent) that SQL deletes would be generated for ALL the children in the collection.
That is not happening. I call delete on the parent and the child row is still present in the database.
I am doing this with a detached object, but I don't think that's the core of the problem. Here is my unit test (patient is the parent class, appointment is the child class):
Code:
public void testAddAppointmentDetached() {
dao.savePatient(patient);
Patient retrievedPatient = dao.retrievePatientByUserName("Patient1");
retrievedPatient.addAppointment(createAppointment());
dao.savePatient(retrievedPatient);
retrievedPatient = dao.retrievePatientByUserName("Patient1");
assertEquals(1, retrievedPatient.getUpcomingAppointmentsCount());
dao.removePatient(patient);
}
This test passes, but to my surprise the dao.removePatient (see code below) is leaving an orphan row in the database. I have even tried adding an explicit line in my DAO to reset the collection of appointments (which shouldn't be necessary I wouldn't think, in the case of a parent deletion). but even that still doesn't delete the child appointment.
What blindingly obvious thing am I missing?
Hibernate version:2.1 Hibernate mapping documentsCode:
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="demo.domain.Patient" table="Patient">
<id name="id" column="PATIENT_ID">
<generator class="increment" />
</id>
<property name="lastName" column="LAST_NAME" type="string" />
<property name="firstName" column="FIRST_NAME" type="string" />
<property name="middleNameOrInitial" column="MIDDLE_NAME"
type="string" />
<property name="birthDate" column="BIRTH_DATE" type="date" />
<property name="age" column="AGE" type="integer" />
<property name="socialSecurityNumber" column="SSN"
type="string" />
<property name="userName" column="USERNAME" type="string" />
<property name="password" column="PASSWORD" type="string" />
<set name="appointments" inverse="true" cascade="all-delete-orphan">
<key column="PATIENT_ID"/>
<one-to-many class="demo.domain.Appointment"/>
</set>
</class>
</hibernate-mapping>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="demo.domain.Appointment" table="Appointment">
<id name="id" column="APPOINTMENT_ID">
<generator class="increment" />
</id>
<property name="time" column="TIME" type="string" />
<property name="clinic" column="CLINIC" type="string" />
<property name="doctor" column="DOCTOR" type="string" />
<property name="appointmentDate" column="APPOINTMENT_DATE" type="date" />
<many-to-one name="patient" column="PATIENT_ID" class="demo.domain.Patient" not-null="true"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
patient.getAppointments().clear();
session.delete(patient);
Name and version of the database you are using: MySQL 4.1
The generated SQL (show_sql=true):
18:27:14,688 INFO SessionFactoryImpl:119 - building session factory
18:27:14,688 INFO ReflectHelper:186 - reflection optimizer disabled for: demo.domain.Patient, BulkBeanException: Property is private (property setAppointments)
18:27:14,708 INFO SessionFactoryObjectFactory:82 - Not binding factory to JNDI, no JNDI name configured
Hibernate: delete from Patient where PATIENT_ID=?
Debug level Hibernate log excerpt: