Motivation:
This article is useful if you need a fast way to update a significant amount of data in the database. Bulk operations (updates and deletes) can be a good choice. Nevertheless, when Hibernate/JPA is involved as well, the bulk operations have some shortcomings that you should be aware of.
150+ PERSISTENCE PERFORMANCE ITEMS
THAT WILL ROCK YOUR APPS
Shortcomings of bulk operations:
Bulk operations (updates and deletes) are faster than batching, can benefit from database indexing, but they have three main shortcomings:
1. Bulk updates/deletes may leave the
Persistence Context in an outdated state
Bulk operations doesn't affect the Persistence Context (1st Level Cache). In other words, Persistence Context doesn't see the modifications performed by bulk operations. This means that it's up to you to prevent this issue by explicitly flushing the Persistence Context before update/delete and close/clear it after the update/delete. This way, you avoid issues
created by potentially unflushed or outdated entities.
2. Bulk updates/deletes don't benefit of
Automatic Optimistic Locking mechanisms
For example, using @Version in your entities is ignored, therefore the lost updates are not prevented. Nevertheless, it is advisable to be a good citizen and signal your updates by explicitly incrementing version as part of your UPDATE query. This way other queries of the application can still use Automatic Optimistic Locking mechanism as expected. Of course, if you don't use @Version or any other Automatic Optimistic Locking mechanism than you don't care about this shortcoming.
3. Bulk deletes cannot take advantage of cascading removals
So, using CascadeType.REMOVE and orphanRemoval is pointless for bulk operations. Both of them will be ignored.
Application example:
This application provides examples of bulk updates for Author and Book entities (between Author and Book there is a bidirectional lazy @OneToMany association). Both, Author and Book, have a version field.
Key points:
Write the repositories for Author and Book (we manually increase thr version field - this way, we support other queries that must take advantage of Automatic Optimistic Locking mechanism):
This application provide an example of bulk updates that don't involve managed entities (data is not loaded in the Persistence Context):
And an example of bulk updates that involve managed entities (data is loaded in the Persistence Context before update it via bulk operations):
Important to know:
The flushAutomatically = true, clearAutomatically = true are not mandatory. As long as you know what you are doing one or both of them can be removed. For flushing you can also rely on flush methods. Also, pay attention that manual/explicit flush is a code smell, therefore use it wisely and only if is needed.
Tam Ta Da Dam! :) The complete application is available on GitHub.
If you need a deep dive into the performance recipes exposed in this repository then I am sure that you will love my book "Spring Boot Persistence Best Practices".
Comments