| 
  
  
     Il 02/03/2016 15:59, christopher
      delahunt ha scritto: 
     
    
      
      Hello Mauro, 
       
      I mistyped when I wrote cascade remove - I meant to write cascade
      merge or cascade persist.  Any references to 'first' could be
      causing it to be resurrected, not just ones from the 'second'
      instance's object graph.  I also noticed you are using cascade
      refresh and lazy relationships - refresh of the referenced entity
      over a lazy reference will be delayed until it is accessed,
      potentially wiping out changes made so far.  Something that causes
      a refresh of firstCollection for instance might get triggered
      after the remove call but before the flush, and cause
      firstCollection to still reference first and cause its
      resurrection in the persistence unit.  I would detail all the
      references in your object model to the 'first' class and check
      that one isn't interfering. 
       
      If you haven't already, I'd recommend turning on EclipseLink
      logging and matching statements up to the calls in your code
      causing them, and trying to determine what is different when the
      issue occurs vs when it doesn't.  You might also try delaying or
      removing the constraint, so that you can see if EclipseLink
      eventually issues the delete so we can see if it is just an
      ordering issue or if it never does, and so is a resurrection issue
      in the application references as mentioned before. 
       
      Best of luck, 
      Chris 
     
     
    Hi Chris, 
    I was "lucky enough" to be able today to reproduce this issue
    locally!! It's very hard to know what is the correct reproduction
    path, anyway... What I observed by debugging is this: 
     
    FirstCollection firstCollection = first.getFirstCollection(); 
    // do some read-only operations on first 
    // remove first from the FirstCollection related
      entities 
     firstCollection.getFirsts().remove(first); 
    // delete first 
    entityManager.remove(first); 
      // added a flush in the hope this fixes the problem 
      entityManager.flush(); (***) 
    // delete the related second instance 
    entityManager.remove(first.getSecond()); 
    // perform a read query on an entity related to first 
     
    Stepping over (***) I saw that the only query that was executed was
    an UPDATE on the FirstCollection table to update the version and
    lastUpdated fields!!! The DELETE FROM First was not issued at all! 
    So, this makes me suspect that the problem is what you are saying: 
    "Something that causes a refresh of firstCollection for instance
    might get triggered after the remove call but before the flush, and
    cause firstCollection to still reference first and cause its
    resurrection in the persistence unit" 
     
    So, I removed the cascade=REFRESH from the relationships in
    FirstCollection and Third that referenced the First entity. 
    However, I'm not sure whether it will work now or not because I
    can't reproduce any more. 
    In fact, I was able to correctly perform the whole deletion once by
    using this code: 
     
    FirstCollection firstCollection = first.getFirstCollection(); 
    // do some read-only operations on first 
    // remove first from the FirstCollection related
      entities 
     firstCollection.getFirsts().remove(first); 
    // first flush 
    
      entityManager.flush(); 
      // delete first 
    entityManager.remove(first); 
      // second flush 
      entityManager.flush(); 
    // delete the related second instance 
    entityManager.remove(first.getSecond()); 
    // perform a read query on an entity related to first 
     
    that is, by performing a first flush before the remove (this caused
    just the UPDATE on the FirstCollection table!) and a second one
    after the remove operation (this one actually performed the DELETE
    FROM First statement!). But having two flushes like this sounded too
    dirty for me, so I decided to try the removal of the cascade=REFRESH
    thing. 
     
    I will monitor the situation for some days and let you know. Anyway,
    if the cascade=REFRESH is the actual problem, this is a really bad
    beast... especially because I'm really doing nothing in between the
    remove and the flush. Also, I would expect
    firstCollections.getFirsts() to be already loaded into memory
    because it has been accessed several times before and the shared
    cache is enabled, so I don't even expect it to be lazy initialised
    when I'm calling that code.  So, there's quite a lot of (black)
    magic here... :-( 
    And I can't explain exactly why two flushes before and after the
    remove would fix the problem. 
     
    Mauro 
  
 |