How to implement the pessimistic lock in Java WEB EJB?

Asked

Viewed 422 times

0

I have competition problems in my system, I need to insert the lock pessimistic because users access and save at the same time, causing bizarre errors in the result.

  • I don’t know about java and Hibernate, but competitive to save data, either you are doing something wrong in the code (time of the Insert/ update) or solve with transaction isolation

1 answer

1

You can use the method lock(Object, LockModeType) of EntityManager. The way of use is this:

AlgumaEntidade x = ...;
EntityManager em = ...;
em.lock(x, LockModeType.PESSIMISTIC_WRITE);

To bring an entity from the database already with the lock pessimistic, use the method find who has a LockModeType as a parameter:

EntityManager em = ...;
AlgumaEntidade x = em.find(AlgumaEntidade.class, pk, LockModeType.PESSIMISTIC_WRITE);

The method refresh, that updates the state of the entity when reread it from the database, also has an overload with LockModeType:

AlgumaEntidade x = ...;
em.refresh(x, LockModeType.PESSIMISTIC_WRITE);

The objects Query (and consequently, TypedQuery and StoredProcedureQuery) also has pessimistic lock support through the method setLockMode(LockModeType):

String jpql = ...;
Query q = em.createQuery(jpql);
q.setLockMode(LockModeType.PESSIMISTIC_WRITE);

As are the other methods of Query, he can be chained:

String jpql = ...;
AlgumaEntidade x = em.createQuery(jpql, AlgumaEntidade.class)
        .setLockMode(LockModeType.PESSIMISTIC_WRITE)
        .setParameter(1, "blabla")
        .getSingleResult();

The annotation NamedQuery also has a field lockMode optional.

The EntityManager also has a method getLockMode(Object) which can be used to find out what type of lock that is being applied to some entity. The Query also has a method getLockMode() that gets the LockModeType which applies to Query.

The Enum LockModeType has the following elements: NONE, OPTIMISTIC, OPTIMISTIC_FORCE_INCREMENT, PESSIMISTIC_FORCE_INCREMENT, PESSIMISTIC_READ, PESSIMISTIC_WRITE, READ and WRITE.

The READ is a synonym for OPTIMISTIC and the WRITE is a synonym for OPTIMISTIC_FORCE_INCREMENT. They exist for historical reasons and in my opinion should be marked as @Deprecated. The historical reason in the case is because they are bequeathed from JPA 1, which only had manners READ and WRITE. As from JPA 2, the part of Locking was revised and reworked, and the other modes were created, making these two existing modes obsolete.

The way NONE is what disables any Locking and let anything happen that happens. This is the default mode for entities that does not contain any field annotated with @Version.

The way OPTIMISTIC is what uses the lock optimistic, but this only works when there is a field @Version. Otherwise, it behaves like NONE. When applied to versioned entities, it allows this to be read by other threads, but not altered or deleted. In the event of competing changes or exclusions, a OptimisticLockException is released.

The way OPTIMISTIC_FORCE_INCREMENT is similar to OPTIMISTIC, but it forces the version to increase. As a consequence, it causes the entity to be modified, so that if there are two threads accessing the same entity in this way, the last one to do the commit will have a OptimisticLockException.

Optimistic modes do not use the mechanism of lock and instead, they do the lock in the application. Already the pessimistic modes delegate the lock to the SGBD.

The way PESSIMISTIC_READ locks tuples in the database for change and deletion, but still allows concurrent readings.

The way PESSIMISTIC_WRITE locks tuples in the database for change, deletion and concurrent readings.

The way PESSIMISTIC_FORCE_INCREMENT is the combination of PESSIMISTIC_WRITE with the OPTIMISTIC_FORCE_INCREMENT. It’s for when you want to use the lock optimistic and pessimistic at the same time or for when you do lock pessimistic in changing versioned entities.

If a lock pessimistic cannot be obtained from the database, a PessimisticLockException is launched.

If the preview JPA needs or wants, it can promote a lock OPTIMISTIC for OPTIMISTIC_FORCE_INCREMENT or a PESSIMISTIC_READ for PESSIMISTIC_WRITE. In particular, it will do so if the entity in question undergoes change or exclusion. It is possible to obtain OptimisticLockException or PessimisticLockException if such promotion is not possible.

Hibernate also has two modes of lock optimist who are not standard of JPA which is the ALL, whether any field of the entity has undergone any concurrent change and the DIRTY verifying whether any of the entity’s modified fields have undergone a concurrent change, but allowing concurrent changes to the other fields.

The pessimistic way has a timeout which can be specified with the property javax.persistence.lock.timeout. It can be specified in the methods of EntityManager which contains a list of properties together with the LockModeType. These methods are, namely: lock; find and refresh. The method setProperty can also be used. It can also be specified in persistence.xml, in the annotation @NamedQuery or when the EntityManagerFactory. When this property has the value 0, it means that we will try to acquire the lock pessimistic immediately and if this is not possible, a LockTimeoutException is immediately launched. If the value is different, the preview JPA waits to try to acquire the lock again before launching a LockTimeoutException. This value is in milliseconds. However this property is only one hint, therefore the preview JPA may choose to disobey her if she so chooses.

More information:

Browser other questions tagged

You are not signed in. Login or sign up in order to post.