This discussion is archived
2 Replies Latest reply: Feb 21, 2012 8:28 AM by cdelahun RSS

Deleting parent entity of oneToMany does not delete children first,

266288 Newbie
Currently Being Moderated
I have two entities related with a bi-rdirectional OneToMany relationship. When I delete the parent, I want eclipseLink to automatically delete the child entities first before deleting the parent entity. I have implemented what I understand all the documents are telling me I should implement, but I can not get it working.

When I try and delete the parent I get an SQLException as the foreign key constraint has been violated as there are child records for the parent I am trying to delete. It was my understanding, that if you have all the annotations correct on my Entities, then all i have to do is delete the parent and eclipseLink will delete the children first and therefore i should never get the SQL exception.

Here is some snippets of my code.


Entities


@Entity(name = "PARENTS")
public class ParentEntity {
     
     @Id
     @Column(name = "PARENT_ID", nullable = false)
     private String parentID;

     @Column(name = "DISPLAY_NAME", nullable = false)
     private String displayName;
     
     @OneToMany(mappedBy="parent", orphanRemoval=true, cascade=CascadeType.ALL)
     private Collection<ChildEntity> childEntities;     

...
}



@Entity(name = "CHILDREN")
@IdClass(ChildIdentifier.class)
public class ChildEntity {

     @Id
     @Column(name="ITEM_ID", nullable=false)
     private String itemID;

     @Id
     @ManyToOne()
     @JoinColumn(name="PARENT_ID", nullable=false)
     private ParentEntity parent;
     
....
}



public class ChildIdentifier implements Serializable {
     private String itemID;
private String parent;
....
}


Tables created from these entities

PARENTS

Name Null? Type
----------------------------------
PARENT_ID NOT NULL VARCHAR2(36)
DISPLAY_NAME NOT NULL VARCHAR2(255)

PrimaryKey = PARENT_ID


CHILDREN

Name Null? Type
-------------------------------
ITEM_ID NOT NULL VARCHAR2(36)
PARENT_ID NOT NULL VARCHAR2(255)

PrimaryKey = ITEM_ID,PARENT_ID
ForeignKey = PARENTID = PARENTS.PARENT_ID


Code to delete a parent

     public void deleteParent(String id)
{
          ParentEntity e= em.find(ParentEntity .class, id);
          if (e!= null)
               em.remove(e);
     }


Exception seen

javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.0.v20120119-r10715): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-02292: integrity constraint (MYSCHEMA.CHILDREN_FK_P_PARENTS) violated - child record found

Error Code: 2292
Call: DELETE FROM PARENTS WHERE (PARENT_ID = ?)




I have added eclipse logging entries in my persistence.xml to try and see what is going on
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>

And in my jdev console when running my test, i do not see any queries of CHILDREN before it tries to delete from PARENTS.


Am I missing something really obvious?

Thanks in advance.

Edited by: smaslin on Feb 20, 2012 9:20 AM

Edited by: smaslin on Feb 21, 2012 5:26 AM
  • 1. Re: Deleting parent entity of oneToMany does not delete children first,
    266288 Newbie
    Currently Being Moderated
    I have even tried having "optional=false" on the child's relationship annotation and it made no difference

    parent
         @OneToMany(mappedBy="parent", orphanRemoval=true, cascade=CascadeType.ALL)
         private Collection<ChildEntity> childEntities;     

    child
         @Id
         @ManyToOne(optional=false)
         @JoinColumn(name="PARENT_ID", nullable=false)
         private ParentEntity parent;

    as per doced here : http://javablog.co.uk/2009/12/27/onetomany-fixes-in-jpa-2/



    I have also tried PrivateOwned annotation, again, it made no difference

    parent
         @OneToMany(mappedBy="parent", orphanRemoval=true, cascade=CascadeType.ALL)
    @PrivateOwned
         private Collection<ChildEntity> childEntities;     


    child
         @Id
         @ManyToOne()
         @JoinColumn(name="PARENT_ID", nullable=false)
         private ParentEntity parent;
  • 2. Re: Deleting parent entity of oneToMany does not delete children first,
    cdelahun Pro
    Currently Being Moderated
    "optional=false" only affects DDL generation, not runtime JPA behavior. PrivateOwned is similar to orphanRemoval in that it should cause the removal of child entities when they are dereferenced from the parent (ie remove them from the parent's collection). Cascade remove or cascade all should be all you need, but PrivateOwned+orphanRemoval should still cause the collection to be removed, as long as there are entities within the Parent's list of children to remove.

    The only case where I can see this not occuring is if you have not been maintaining the bidirectional relationship. That is, if you have added Child entities and set a parent, but not updated the Parent's collection of children to reflect that change. A simple test is to refresh the parent before removal - call em.refresh(e); right before the em.remove(e);. If this works, then you will need to change your application so that when you add parents to a child you also add the child to the parent's list of children - JPA does not maintain relationships for you and not doing so will keep the cache inconsistent with what is in the database.

    Best Regards,
    Chris

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points