spring-boothibernatejpasql-deletecascading-deletes

Asking for advice on debugging a not-working JPA delete call


We're having a rather complex table structure in our Spring Boot application, consisting of about ten entities linked by one-to-one, one-to-many, many-to-one and many-to-many relations. They're implemented as JPA entities and we use CrudRepository or JpaRepository to handle them. So far, everything is working fine, our entities are created and updated as desired, complying with the relations given.

Now, there's the need to delete some of the entities. Let's assume, the structure looked like this:

   A
 /   \
B     C
      |
      D - E

(As said, our real structure is much more complex and contains more entities, I don't think, it makes sense to outline it here.)

If I just delete A using its repository class, the whole tree is deleted as desired. The problem is, we must not delete A, but everything related to it, except for one or two entities, like e. g. E here. So, one should go with deleting B and then C individually. (E. g. CRepository.deleteAll(cChildrenOfTheAObjectInQuestion);.

The problem is, this just doesn't work. I've logged the SQL output using

logging:
  level:
    org.hibernate.SQL: DEBUG

and so on and I can see a lot of SELECT statements when the delete line is carried out, but nothing more. Nothing is deleted from the database.

I have checked the cascade constraints and relation annotations multiple times, tried with and without @Transactional, tried to delete D first, then C and so on. Nothing really helps, just sometimes a few of the "leaf" entities (farer away from A) are deleted.

So, without supplying our real entity structure and code, which I think would be a big overhead and not useful, I would like to kindly ask for conceptual advice on debugging the whole situation.

Is there any step-by-step guidance I could follow in order to approach the root problem? Or can I get any more output from JPA (like "not deleting entity XY, because...")? Any helpful hint is appreciated!

As a last resort, I could use plain SQL to delete the entities or even delete the whole tree by deleting A and then recreate this A and the other entities needed. But both seem quite nasty and unelegant to me.

Many thanks in advance!


Solution

  • I guess the problem is that A propagates the persist status for the associated entities. Check the cascade property between A and B/C.

    To get more output from Hibernate you can enable trace logging level:

    logging.level.org.hibernate=trace
    

    and look for something like this in the log:

    org.hibernate.engine.internal.Cascade    : Cascade ACTION_PERSIST_ON_FLUSH for collection: com.example.spring3demo.entity.Owner.pets
    o.hibernate.engine.spi.CascadingAction   : Cascading to persist on flush: com.example.spring3demo.entity.Pet
    o.hibernate.event.internal.EntityState   : Deleted instance of: com.example.spring3demo.entity.Pet
    o.h.e.i.DefaultPersistEventListener      : un-scheduling entity deletion [[com.example.spring3demo.entity.Pet#2]]
    

    Also you can try to debug: open Hibernate's class SessionImpl and put breakpoints into beforeTransactionCompletion and afterTransactionCompletion and check how the statuses of entities were changed in the end of transaction (SessionImpl -> persistenceContext -> entityEntryContext)