Concurrency with Hibernate in Spring

I found a lot of posts on this topic, but all the answers were just links to documentation without example code, i.e. how to use concurrency in practice.

My situation: I have a House entity with (for simplicity) two attributes, number (id) and owner . The database is initialized to 10 Houses with number 1-10 and owner always null .

I want to appoint a new owner in a house in which there is no owner now, and the smallest number . My code is as follows:

 @Transactional void assignNewOwner(String newOwner) { //this is flagged as @Transactional too House tmp = houseDao.getHouseWithoutOwnerAndSmallestNumber(); tmp.setOwner(newOwner); //this is flagged as @Transactional too houseDao.update(tmp); } 

For my understanding, although @Transactional used, the same House can be assigned twice for different owners if two requests receive the same empty House as tmp . How can I guarantee that this cannot be?

I know, including updating when choosing an empty House will solve the problem, but in the near future I want to change / work with the tmp object more.

+5
source share
2 answers

Optimistic

If you add a version column to your entity / table, you can use the Optimistic Locking mechanism. This is the most experienced way to make sure that the state of an object has not changed since it was received in a transactional context.

After createQuery using session you can call setLockMode(LockModeType.OPTIMISTIC);

Then, shortly before the transaction is completed, the save provider will request the current version of this object and check if it has been enlarged by another transaction. If so, you will get an OptimisticLockException and transaction rollback.

Pessimistic

If you do not update your rows, you are left with a pessimistic lock, which basically means that you physically create a lock for queries at the database level, and other transactions cannot read / update certain rows.

You achieve this by setting this to a Query object:

setLockMode(LockModeType.PESSIMISTIC_READ);

or

setLockMode(LockModeType.PESSIMISTIC_WRITE);

+1
source

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.

+1
source

Source: https://habr.com/ru/post/1272716/


All Articles