2

I am using Java Spring Framework and Hibernate. I am doing a e-commerce web application where public user is able to purchase product from the web app. Each product will have a quantity count.

Issue

I want to prevent the scenario where two concurrent users purchase the same product is left with quantity value 1. In this case, only the first user should get to purchase the product while the second user should receive a "no stock available" message.

Workflow

I intend to decrement the quantity count and then send the purchase information to the payment gateway. If payment gateway encounters payment issue, I will increment the quantity count. The lock will be released before purchase info is sent to payment gateway.

So my question is,

1) I would like to confirm this answer on pessimistic locking does help solves my issue.

2) Is my workflow ok? Is there a better way to do this?

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
CodeBender
  • 267
  • 4
  • 14

1 Answers1

7

You can also use optimistic locking and prevent possible lost updates.

With optimistic locking, if two users have loaded the same entity with a quantity of 1, and one user has just made a purchase and decremented the quantity counter, then the second user won't be able to UPDATE the product entity since his Product version doesn't match the one that was found in the database at the moment when the entity was read.

If the entity version changes, then the UPDATE statement that tries to match the old version will return a 0 when the executeUpdate method of the PreparedStatement is called. That's when Hibernate will detect the stale state situation and throw an OptimisticLockException.

The Spring TransactionInterceptor will catch the OptimisticLockException, and the associated transaction will be rolled back.

The optimistic locking approach scales better than pessimistic locking, and it also works on multi-request logical transactions.

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
  • Thanks! In the case for the second user who attempts an update on the changed value (by first user), is it sound if I will just retry? retry means refetch the quantity count on a new session and decrement it again. – CodeBender Apr 12 '15 at 02:31
  • 1
    I think it's safer to let the user retry manually. Maybe ha was updating the product name and you don't want to lose that update. Only if you move the quantity to a ProductStock entity, you can isolate changes to quantity and therefore retry automatically the transaction. – Vlad Mihalcea Apr 12 '15 at 06:02
  • Awesome. Appreciates the help there! =D – CodeBender Apr 12 '15 at 09:50
  • @VladMihalcea what happens if there are more than 2 users, imagine if the numbers are in 100 then don't you think this optimistic locking will degrade the performance?? In that case, what can we do – dilipyadav May 27 '22 at 07:56
  • 1
    This strategy works fine if there are 100 users because each user interacts with different things in a system. Some operations are commutative and don't need optimistic locking. However, for the use cases that require preventing a lost update, getting a failure and retrying afterward is better than generating a data anomaly that can lead to bankruptcy, as it was the case for FlexCoin. Check out [this video](https://www.youtube.com/watch?v=2qXJI7kG1ig) for more details. – Vlad Mihalcea May 27 '22 at 09:56