1

In my Java EE application, I have two persistent entities Worklist and Task with these JPA relationships:

Worklist entity:

 public class WorkList implements Serializable {
    ...
    @OneToMany(cascade={CascadeType.PERSIST, CascadeType.REMOVE} , mappedBy ="worklist")
    private List<Task> tasks;
    ...
    }

And the Task entity:

  public class Task implements Serializable {
    ...
    @ManyToOne
    private WorkList worklist;
    ...
    }

I indicated the cascade type in Worklist as:

  cascade={CascadeType.PERSIST, CascadeType.REMOVE}

So, I can persist a Worklist and a list of tasks that are associated to this Worklist but I have a problem when I try to delete a Worklist and I have this exception:

Avertissement: Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461):  
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception:  
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot  
delete or update a parent row: a foreign key constraint fails (`scopedata`.`TASKS`, 
CONSTRAINT `FK_TASKS_WORKLIST_id` FOREIGN KEY (`WORKLIST_id`) REFERENCES `WORKLISTS` 
(`id`))
Error Code: 1451
Call: DELETE FROM WORKLISTS WHERE ((id = ?) AND (version = ?))
bind => [2 parameters bound]
Query: DeleteObjectQuery(WokList{id=bbf05bdb-1314-4b07-9f4e-69898b800c00, creation=Thu
Nov 28 08:39:21 CET 2013, startDate=Thu Nov 07 00:00:00 CET 2013, endDate=Fri Nov 15
00:00:00 CET

On the other side, I can successfully delete a Task.

This is the methode in the WorklistManager.java that removes a worklist

   @Override
     public boolean deleteWorkList(WorkList workList) {
       if (findWorkList(workList)) {
        em.remove(em.merge(workList));
        return true;
    }
    return false;
    }

Then, I call this methode in the Managed Bean:

    public String deleteWorkList() {
    workListManagerLocal.deleteWorkList(selectedWorkList);
    return "index";
  }

I am working with: JPA2 and Glassfish 3.1.2.2.

Reem
  • 169
  • 1
  • 4
  • 15
  • Please go through this thread: http://stackoverflow.com/questions/306144/jpa-cascadetype-all-does-not-delete-orphans It seems to me that the behaviour of orphan removal is very implementation specific. But have a look yourself! – Balázs Németh Nov 28 '13 at 09:24
  • Log the SQL queries made EclipseLink and post them in your question. It seems that the order of the SQL queries is wrong. – V G Nov 28 '13 at 11:07
  • @AndreiI Now it works but only for the first time after running the project, second time, the same exception is displayed. In fact, I have two datatables. The first shows all **Worklists** then the user select one to show the **list** of associated **Tasks** (the second datatable). So, I injected **Worklist** Managed Bean into **Task** Managed Bean to recuperate the Id of the **selectedWorklist**. – Reem Nov 28 '13 at 13:11
  • When you go to remove the WorkList, what is in the worklist's tasks collection? My bet is that you have not been maintaining both sides of your bidirectional relationship, so that tasks reference Worklist but these worklists do not have task references. If this is the case, the cascade remove will not work, as JPA has no way of knowing about the other tasks it needs to clean up. JPA does not perform relationship maintenance - it is up to the application to keep both sides of bidirectional relationships in synch with each other. – Chris Dec 02 '13 at 14:14

1 Answers1

1
  1. Add the orphanRemoval=true property to your @OneToMany relationship.
  2. Instead of calling em.merge() in your public boolean deleteWorkList(WorkList workList) make a managedWorklist = em.find(Worklist.class, workList.getId()) and than delete the returned worklist: em.remove(managedWorklist) and DO NOT CALL findWorkList() as you already do that in your code.
V G
  • 18,822
  • 6
  • 51
  • 89