DEV Community

Rida F Najid
Rida F Najid

Posted on

Optimistic Locking on Spring Boot

If your application has massive traffic. Sometimes there will be conflicting updates between data.

For example, User A and User B accidentally trying to update same data on same time. Both of their updates will be saved and both users will receive a successful response. Both of them will assume their data correctly saved. But, that's not the case - the first saved data will replaced by the last one. We don't know which user saved it first.

In order to prevent this, we can use Optimistic Locking. In Optimistic Locking we need to save record version in database.

optimistic locking example

If there's modification on a record, we need to check its version first. If the new data version is lower than the version in the database, it will be rejected. If it has the correct version, the new data will be saved and the version will be incremented.

It has quite a lot logic right? But, don't worry all of that process will be taken care by JPA.

We need to add the @version annotation to the entity.

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;

    String name;

    @Version
    Long version;
}
Enter fullscreen mode Exit fullscreen mode

All done!

Here's a test script to check if Optimistic Locking is working correctly.

@DataJpaTest
public class RepoTest {

    @Autowired
    StudentRepository repo;

    @Test
    void testOptimisticLock(){
        Student initStudent = new Student(1L, "Andy", 0L);
        Student insertedStudent = repo.saveAndFlush(initStudent);

        assertEquals(0, insertedStudent.getVersion());

        insertedStudent.setName("Jack");
        Student updatedStudent = repo.saveAndFlush(insertedStudent);

        assertEquals(1, updatedStudent.getVersion());

        assertThrows(OptimisticLockingFailureException.class, () ->
            repo.saveAndFlush(initStudent)
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

You can check the full code here

*Note *

If you don't want to add dedicated version field to your existing table, you can use the update date as the version instead.

Top comments (0)