Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concurrency with Hibernate in Spring

I found a lot of posts regarding this topic, but all answers were just links to documentations with no example code, i.e., how to use concurrency in practice.

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

I want to assign a new owner to the house with currently no owner, and the smallest number. My code looks like this:

@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 the @Transactional is used, the same House could be assigned twice to different owners, if two requests fetch the same empty House as tmp. How do I ensure this can not happen?

I know, including the update in the selection of the empty House would solve the issue, but in near future, I want to modify/work with the tmp object more.

like image 488
Thanthla Avatar asked Oct 29 '22 00:10

Thanthla


1 Answers

Optimistic

If you add a version column to your entity / table then you could take advantage of a mechanism called Optimistic Locking. This is the most proficient way of making sure that the state of an entity has not changed since we obtained it in a transactional context.

Once you createQuery using the session you can then call setLockMode(LockModeType.OPTIMISTIC);

Then, just before the transaction is commited, the persistence provider would query for the current version of that entity and check whether it has been incremented by another transaction. If so, you would get an OptimisticLockException and a transaction rollback.

Pessimistic

If you do not version your rows, then you are left with pessimistic lockin which basically means that you phycically create a lock for queries entities on the database level and other transactions cannot read / update those certain rows.

You achieve that by setting this on the Query object:

setLockMode(LockModeType.PESSIMISTIC_READ);

or

setLockMode(LockModeType.PESSIMISTIC_WRITE);

like image 121
Maciej Kowalski Avatar answered Nov 04 '22 15:11

Maciej Kowalski