-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Simple But Crazy Cascade Problem
PostPosted: Sat Aug 20, 2011 10:22 pm 
Newbie

Joined: Sat Aug 20, 2011 10:00 pm
Posts: 4
Although I'm using javax.persistence.CascadeType.ALL, org.hibernate.annotations.CascadeType.ALL, and OnDeleteAction.CASCADE I couldn't manage to delete parent row.
My code is like that:
Code:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Person
{
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private int personId;
//other fields getters setters
}

@Entity
public class Patient extends Person
{
   // bi-directional many-to-one association to Doctor
   @ManyToOne(optional = false, targetEntity=Doctor.class)
   @JoinColumn(name = "doctorId", nullable = false)
   private Doctor doctor;
   //getter/setters, no other fields, just doctor
}

@Entity
public class Doctor extends Person
{
   // bi-directional many-to-one association to Patient
   @OneToMany(mappedBy = "doctor", orphanRemoval = true, cascade = { javax.persistence.CascadeType.ALL })
   @Cascade({ CascadeType.ALL })
   @ForeignKey(name = "FK_DOCTOR")
   @OnDelete(action = OnDeleteAction.CASCADE)
   private List<Patient> patients;
   //getter/setters, no other fields, just patients
}

public boolean deleteDoctor(Doctor doctor)
{
   EntityManager em = null;
   EntityTransaction entityTransaction = null;
   boolean result = false;
   try
   {
      em = getEntityManagerFactory().createEntityManager();
      entityTransaction = em.getTransaction();
      entityTransaction.begin();
      doctor = em.merge(doctor);
      em.remove(doctor);
      entityTransaction.commit();
      result = true;
   }
   catch (Exception exception)
   {
      exception.printStackTrace();
   }
   em.close();
   return result;
}


I have one base class Person and 2 inherited classes Doctor and Patient. One doctor can have one or more patients but a patient is related to only one doctor. That is so simple. But for hours I couldn't delete a doctor that have patients referencing on it. I want the patients to be deleted when their doctor is deleted.
The exception trace is:

Code:
HibernateLog --> 05:20:32 WARN  org.hibernate.util.JDBCExceptionReporter - SQL Error: 1451, SQLState: 23000
HibernateLog --> 05:20:32 ERROR org.hibernate.util.JDBCExceptionReporter - Cannot delete or update a parent row: a foreign key constraint fails (`mobilhm`.`patient`, CONSTRAINT `FK_DOCTOR` FOREIGN KEY (`doctorId`) REFERENCES `doctor` (`personId`))
javax.persistence.RollbackException: Error while committing the transaction
   at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:93)
   at tr.com.stigma.mobilhm.db.controller.service.DoctorServiceImpl.deleteDoctor(DoctorServiceImpl.java:139)
   at tr.com.stigma.test.mobilhm.db.controller.PatientServiceImplTest.tearDownAfterClass(PatientServiceImplTest.java:52)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:597)
   at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
   at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
   at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
   at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:37)
   at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
   at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not delete: [tr.com.stigma.mobilhm.db.entity.Doctor#10]
   at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1215)
   at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1148)
   at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:81)
   ... 17 more
Caused by: org.hibernate.exception.ConstraintViolationException: could not delete: [tr.com.stigma.mobilhm.db.entity.Doctor#10]
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
   at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2728)
   at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2911)
   at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:97)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:189)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
   at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:76)
   ... 17 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`mobilhm`.`patient`, CONSTRAINT `FK_DOCTOR` FOREIGN KEY (`doctorId`) REFERENCES `doctor` (`personId`))
   at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
   at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
   at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
   at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
   at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
   at com.mysql.jdbc.Util.getInstance(Util.java:386)
   at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039)
   at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3597)
   at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3529)
   at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1990)
   at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2151)
   at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2625)
   at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2415)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2333)
   at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2318)
   at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2710)
   ... 28 more

What I need to do? I'm using all deletion cascades, orphan removal etc.
Please tell me the problem. It must work, isn't it?


UPDATE:

I've looked at the generated schema:
Code:
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    drop table if exists mobilhm.Doctor
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    drop table if exists mobilhm.Patient
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    drop table if exists mobilhm.Person
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    drop table if exists mobilhm.User
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    create table mobilhm.Doctor (
        personId integer not null,
        primary key (personId)
    )
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    create table mobilhm.Patient (
        personId integer not null,
        doctorId integer not null,
        primary key (personId)
    )
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    create table mobilhm.Person (
        personId integer not null auto_increment,
        address varchar(255),
        birthDate varchar(255),
        height float not null,
        name varchar(255) not null,
        phone varchar(255),
        sex integer not null,
        surname varchar(255) not null,
        weight float not null,
        userId integer not null,
        primary key (personId),
        unique (userId)
    )
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    create table mobilhm.User (
        userId integer not null auto_increment,
        password varchar(32) not null,
        username varchar(32) not null unique,
        primary key (userId)
    )
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    alter table mobilhm.Doctor
        add index FK7A547D3FAB36233C (personId),
        add constraint FK7A547D3FAB36233C
        foreign key (personId)
        references mobilhm.Person (personId)
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    alter table mobilhm.Patient
        add index PATIENT_DOCTOR_FK (doctorId),
        add constraint PATIENT_DOCTOR_FK
        foreign key (doctorId)
        references mobilhm.Doctor (personId)
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    alter table mobilhm.Patient
        add index FK340C82E5AB36233C (personId),
        add constraint FK340C82E5AB36233C
        foreign key (personId)
        references mobilhm.Person (personId)
HibernateLog --> 16:05:57 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport -
    alter table mobilhm.Person
        add index PERSON_USER_FK (userId),
        add constraint PERSON_USER_FK
        foreign key (userId)
        references mobilhm.User (userId)


with the mapping for these annotation configuration:
Code:
@Entity
public class User
{
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private int userId;
   @Column(length = 32, nullable = false, unique = true)
   private String username;
   @Column(length = 32, nullable = false)
   private String password;
   @OneToOne(mappedBy = "user")
   @Cascade({ CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE })
   private Person person;
}

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Person
{
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private int personId;
   private int sex;
   @Column(nullable = false)
   private String name;
   @Column(nullable = false)
   private String surname;
   private String phone;
   private String address;
   private String birthDate;
   private float height;
   private float weight;
   @OneToOne(optional = false)
   @JoinColumn(name = "userId")
   @Cascade({ CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE })
   @ForeignKey(name = "PERSON_USER_FK")
   @OnDelete(action = OnDeleteAction.CASCADE)
   private User user;
}

@Entity
public class Patient extends Person
{
   // bi-directional many-to-one association to Doctor
   @ManyToOne(optional=false)
   @JoinColumn(name = "doctorId", nullable=false)
   @ForeignKey(name = "PATIENT_DOCTOR_FK")
   @OnDelete(action = OnDeleteAction.CASCADE)
   private Doctor doctor;
}

@Entity
public class Doctor extends Person
{
   // bi-directional many-to-one association to Patient
   @OneToMany(mappedBy = "doctor", orphanRemoval = true)
   @Cascade({ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE })
   private List<Patient> patients;
}


As you see hibernate is aware of foreign keys PERSON_USER_FK and PATIENT_DOCTOR_FK but doesn't generate Cascade statements. I will go mad please help me.


Top
 Profile  
 
 Post subject: Re: Simple But Crazy Cascade Problem
PostPosted: Mon Aug 22, 2011 5:21 am 
Newbie

Joined: Sat Aug 20, 2011 10:00 pm
Posts: 4
Nobody knows?


Top
 Profile  
 
 Post subject: Re: Simple But Crazy Cascade Problem
PostPosted: Wed Feb 01, 2012 12:11 pm 
Newbie

Joined: Fri Dec 23, 2011 7:40 pm
Posts: 12
Did you ever find a fix for this? I seem to be running into the same problem.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.