{"id":55441,"date":"2022-09-09T11:38:07","date_gmt":"2022-09-09T06:08:07","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=55441"},"modified":"2022-09-13T11:42:41","modified_gmt":"2022-09-13T06:12:41","slug":"optimistic-locking-in-spring-boot","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/optimistic-locking-in-spring-boot\/","title":{"rendered":"Optimistic Locking in Spring Boot"},"content":{"rendered":"<h3><strong>Overview<\/strong><\/h3>\n<p><span style=\"font-weight: 400;\">We know that for large-scale software applications that handle a large number of database transactions, implementing a concurrency management mechanism is essential so that we can handle multiple database calls simultaneously and effectively without any data loss<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">One of the ways to implement concurrency control is the <strong>optimistic locking<\/strong> mechanism provided by <strong>Java Persistence API<\/strong>.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Contrary to pessimistic locking, optimistic locking doesn\u2019t apply locks on the database and hence reduces the isolation level of the system and increases the throughput capacity of the software. Also, there is no chance of deadlock in this like in pessimistic locking.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">It allows transactional conflicts to occur and detects them while committing the transaction, and then we can handle the flow according to our use case.<\/span><\/p>\n<h3><b>Implementation of Optimistic Locking<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">The implementation of optimistic locking is simple. It can be implemented using a new property <\/span><b>version<\/b><span style=\"font-weight: 400;\"> in the entity (annotating it with @Version). Although there have been multiple implementations of this attribute, the most effective and widely used is a simple integer type numeric counter type version whose value will be auto-incremented each time we update the data. We also need to ensure that the entity&#8217;s state is not getting fetched from the cache for this.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-55439 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/09\/f.png\" alt=\"\" width=\"722\" height=\"300\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/09\/f.png 722w, \/blog\/wp-ttn-blog\/uploads\/2022\/09\/f-300x125.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/09\/f-624x259.png 624w\" sizes=\"(max-width: 722px) 100vw, 722px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Let\u2019s try to understand the use of the version attribute.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-55440 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/09\/fb.png\" alt=\"\" width=\"1209\" height=\"245\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/09\/fb.png 1209w, \/blog\/wp-ttn-blog\/uploads\/2022\/09\/fb-300x61.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/09\/fb-1024x208.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/09\/fb-768x156.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/09\/fb-624x126.png 624w\" sizes=\"(max-width: 1209px) 100vw, 1209px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">1) Both investor1 and investor2 will fetch the same data with, let\u2019s say version=1,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">2) investor1 will be saved first, and the version will be automatically updated to 2(vesrion=version+1).<\/span><\/p>\n<p><span style=\"font-weight: 400;\">3) now, when we try to save investor2, the query similar to the following query will be run<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>Update investor\u00a0<\/b><\/p>\n<p><b>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Set version=2, firstName=\u2019XYZ\u2019<\/b><\/p>\n<p><b>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Where uuid=randomUuid<\/b><\/p>\n<p><b>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 and version=1<\/b><\/p>\n<p><span style=\"font-weight: 400;\">\u00a04) now as we know, that version is already updated by investor1 while saving, so no row will be fetched while updating investor2, and <\/span><b>optimisticLockingException <\/b><span style=\"font-weight: 400;\">will be thrown for investor2 hence preventing the silent data loss of investor1.<\/span><\/p>\n<h3><b>Handling of optimisticLockingException:<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">There are mainly two ways to handle this exception:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">1) In the catch block, we can fetch the data again for investor2, then try to make changes in the data if possible and then try saving the data again.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">2) The Second option could be that we just show a message to the user that either some other user updated the data or an error has occurred and ask the user to update the data again.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">So depending on our use cases, we can implement either of the above methods.<\/span><\/p>\n<h3>Conclusion<\/h3>\n<p><span style=\"font-weight: 400;\">Although optimistic locking cannot be implemented to handle all types of concurrency issues, whether to implement optimistic locking depends on a case-by-case basis. For example, it can be used where there are more read transactions than written transactions. It can be used where we don\u2019t want a single transaction to acquire the lock on a database or, in fact, where we can afford the loss of data. Also, like in pessimistic locking, it doesn&#8217;t put a lock on the data, so it can be used where we put data into a detached state after fetching it, but at the same time, needless to say, pessimistic locking provides greater data integrity.<\/span><\/p>\n<p>&nbsp;<\/p>\n<pre><\/pre>\n<p>&nbsp;<\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>Overview We know that for large-scale software applications that handle a large number of database transactions, implementing a concurrency management mechanism is essential so that we can handle multiple database calls simultaneously and effectively without any data loss. One of the ways to implement concurrency control is the optimistic locking mechanism provided by Java Persistence [&hellip;]<\/p>\n","protected":false},"author":1489,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":215},"categories":[446],"tags":[5015],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/55441"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1489"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=55441"}],"version-history":[{"count":9,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/55441\/revisions"}],"predecessor-version":[{"id":55465,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/55441\/revisions\/55465"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=55441"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=55441"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=55441"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}