This is actually pretty easy - at least in my opinion, and I'm going to take my mind off of what Hibernate will generate when you say Pessimistic/Optimistic . You might think that this is SELECT FOR UPDATE - but this is not always the case, MSSQL AFAIK does not have this ...
These are JPA annotations, and they guarantee some functionality, not implementation.
In essence, these are completely different things - a PESSIMISTIC vs OPTIMISTIC . When you do a pessimistic lock, you at least logically execute a synchronized block - you can do whatever you want and you are safe within the transaction. Now, no matter what lock is held for row, table or even page , it is not specified; so a little dangerous. Typically, a database can escalate locks; MSSQL does this if I call back correctly.
Obviously locking fasting is a problem, so you might think that OPTIMISTIC locking will help. As a side note, this is what transactional memory is in modern CPU ; they use the same thinking process.
Thus, an optimistic lock is similar to a statement - I will mark this line with an identifier / date, etc., then I will take a picture of it and work with it - before committing, I will check if this identifier has changed. Obviously, there is a conflict on this ID , but not on the data. If it has changed - abort (aka throw OptimisticLockException ), otherwise do the work.
The thing that bothers all IMOs is that OptimisticLockException - how did you recover from this? And thatโs what you donโt like - it depends. There are applications in which a simple retry is sufficient; there are applications where this would be impossible. I used it in rare scenarios.
Usually I use PESSIMISTIC lock (if OPTIMISTIC not completely an option). At the same time, I would look at what sleep mode is generating for this request. For example, you might need an index on how a record is retrieved for a DB to actually lock only the row - because ultimately this is what you want.