How To Batch Deletes In MySQL Via orphanRemoval=true
Description: Batch deletes in MySQL via orphanRemoval=true
.
Note: Spring deleteAllInBatch()
and deleteInBatch()
don't use delete batching and don't take advantage of cascading removal, orphanRemoval
and automatic optimstic locking mechanism to prevent lost updates (e.g., @Version
is ignored). They rely on Query.executeUpdate()
to trigger bulk operations. These operations are fast, but Hibernate doesn’t know which entities are removed, therefore, the Persistence Context is not updated accordingly (it's up to you to flush (before delete) and close/clear (after delete) the Persistence Context accordingly to avoid issues created by unflushed (if any) or outdated (if any) entities). The first one (deleteAllInBatch()
) simply triggers a delete from entity_name
statement and is very useful for deleting all records. The second one (deleteInBatch()
) triggers a delete from entity_name where id=? or id=? or id=? ...
statement, therefore, is prone to cause issues if the generated DELETE
statement exceedes the maximum accepted size. This issue can be controlled by deleting the data in chunks, relying on IN
operator, and so on. Bulk operations are faster than batching which can be achieved via the deleteAll()
, deleteAll(Iterable<? extends T> entities)
or delete()
method. Behind the scene, the two flavors of deleteAll()
relies on delete()
. The delete()
/deleteAll()
methods rely on EntityManager.remove()
therefore the Persistence Context is synchronized accordingly. If automatic optimstic locking mechanism (to prevent lost updates) is enabled then it will be used. Moreover, cascading removals and orphanRemoval
works as well.
Key points for using deleteAll()/delete()
:
- in this example, we have a
Author
entity and each author can have severalBook
(one-to-many) - first, we use
orphanRemoval=true
andCascadeType.ALL
- second, we dissociate all
Book
from the correspondingAuthor
- third, we explicitly (manually) flush the Persistent Context; is time for
orphanRemoval=true
to enter into the scene; thanks to this setting, all disassociated books will be deleted; the generatedDELETE
statements are batched (iforphanRemoval
is set tofalse
, a bunch of updates will be executed instead of deletes) - forth, we delete all
Author
via thedeleteAll()
ordelete()
method (since we have dissaciated allBook
, theAuthor
deletion will take advantage of batching as well)