Reputation: 474
Is there an option in JPA to load an entity (or a list of) without locking the database? I would like to be able to do it in just a few methods. Also is it possible for JPA to load the entity without locking the database, BUT when anything change on that entity, just then it lock the row in the database? Validating the state of course, if the entity is already changed in the database throws an exception of invalid state.
Upvotes: 0
Views: 1217
Reputation: 8219
Is there an option in JPA to load an entity (or a list of) without locking the database?
Entities can be loaded by means of different EntityManager's calls:
EntityManager.find
EntityManager.createQuery
EntityManager.createNamedQuery
EntityManager.createNativeQuery
You don't need to use LockModeType.None
explicitly in these calls. This is the default option in JPA represented by LockModeType.None
.
Also is it possible for JPA to load the entity without locking the database, BUT when anything change on that entity, just then it lock the row in the database?
Entities can be locked by means of different calls:
EntityManager.find
EntityManager.lock
EntityManager.refresh
Query.setLockMode
I would say it is possible but not guaranteed by JPA as it depends on the persistence provider (vendor-specific) and type of locking being used.
Anyway such scenario may have look like this:
// begin tx
...
SomeEntity e = em.find(SomeEntity.class, id);
// change the entity
em.lock(e, LockModeType.OPTIMISTIC); // LockModeType.OPTIMISTIC_FORCE_INCREMENT
...
// commit tx
Now, it depends on a persistence provider whether locking will be eager (when lock is called) or deferred (when tx completes). Keep in mind that another transaction may lock the entity as the first one and you will end up with rollback.
From JPA Specification 2.0, chapter 3.4.4.1 OPTIMISTIC, OPTIMISTIC_FORCE_INCREMENT:
If transaction
T1
callslock(entity, LockModeType.OPTIMISTIC)
on a versioned object, the entity manager must ensure that neither of the following phenomena can occur:
- P1 (Dirty read): Transaction
T1
modifies a row. Another transactionT2
then reads that row and obtains the modified value, beforeT1
has committed or rolled back. TransactionT2
eventually commits successfully; it does not matter whetherT1
commits or rolls back and whether it does so before or afterT2
commits.- P2 (Non-repeatable read): Transaction
T1
reads a row. Another transactionT2
then modifies or deletes that row, beforeT1
has committed. Both transactions eventually commit successfully.This will generally be achieved by the entity manager acquiring a lock on the underlying database row. While with optimistic concurrency, long-term database read locks are typically not obtained immediately, a compliant implementation is permitted to obtain an immediate lock (so long as it is retained until commit completes). If the lock is deferred until commit time, it must be retained until the commit completes. Any implementation that supports repeatable reads in a way that prevents the above phenomena is permissible
If transaction
T1
callslock(entity,LockModeType.OPTIMISTIC_FORCE_INCREMENT)
on a versioned object, the entity manager must avoid the phenomena P1 and P2 (as withLockModeType.OPTIMISTIC
) and must also force an update (increment) to the entity's version column. A forced version update may be performed immediately, or may be deferred until a flush or commit.
Upvotes: 1