Tuesday 8 December 2009

Locking in JPA 2.0

1.     Introduction
The JPA specification 2.0 assumes that the databases to which persistence units are mapped will be accessed by the implementation using read-committed isolation (or a vendor equivalent in which long-term read locks are not held).

2.     Optimistic Locking
Optimistic locking is a technique that is used to insure that updates (merge operation) to the database data corresponding to the state of an entity are made only when no intervening transaction has updated that data since the entity state was read.

Version Attributes
The Version field or property is used by the persistence provider to perform optimistic locking. An entity is automatically enabled for optimistic locking if it has a property or field mapped with a Version mapping.

@Entity
@Table(name = "ITEMS")
public class Item implements Serializable {
         
          @Id
          @Column(name = "ITEM_ID")
          private Long itemId;
         
@Column(name = "ITEM_NAME")
          private Long itemName;

          @Version
          @Column(name = "OPT_LOCK")
          private Integer version;
         
         
}

The persistence provider's implementation of the merge operation must examine the version attribute when an entity is being merged and throw an OptimisticLockException if it is discovered that the object being merged is a stale copy of the entity—i.e. that the entity has been updated since the entity became detached.

The version attribute is updated by the persistence provider runtime when the object is written to the database.

UPDATE ITEMS SET ITEM_NAME = 'Name test', OPT_LOCK = 2 WHERE ITEM_ID = 700 AND OPT_LOCK = 1

Optimistic lock modes
If transaction calls lock(entity, LockModeType.OPTIMISTIC) on a versioned object, the entity manager must ensure that neither dirty read nor non-repeatable read occurs.

If transaction calls lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT) on a versioned object, the entity manager must ensure that neither dirty read nor non-repeatable read occur and force an increment to the version at the end of the transaction, even if the entity is not modified.

Note: LockModeType.OPTIMISTIC is synonymous with LockModeType.READ and LockModeType. OPTIMISTIC_FORCE_INCREMENT is synonymous with LockModeType.WRITE.

3.     Pessimistic Locking
Pessimistic concurrency locks the database row when data is read and it ensures that transactions do not update the same entity at the same time, which can simplify application code, but it limits concurrent access to the data which can cause bad scalability and may cause deadlocks. Pessimistic locking is better for applications with a higher risk of contention among concurrent transactions. 

Pessimistic locking guarantees that once a transaction has obtained a pessimistic lock (long-term database locks) on an entity instance:

No other transaction (whether a transaction of an application using the Java Persistence API or any other transaction using the underlying resource) may successfully modify or delete that instance until the transaction holding the lock has ended.

If the pessimistic lock is an exclusive lock (LockModeType.PESSIMISTIC_WRITE or LockModeType.PESSIMISTIC_FORCE_INCREMENT), that same transaction may modify or delete that entity instance.

A persistence provider may use an underlying database platform's SELECT FOR UPDATE statements to implement pessimistic locking if that construct provides appropriate semantics, or the provider may use an isolation level of repeatable read.

Pessimistic lock modes
These lock modes are used to immediately obtain long-term database locks. Any locks must be obtained immediately and retained until transaction completes (commits or rolls back).

If transaction calls lock(entity, LockModeType.PESSIMISTIC_READ) or lock(entity, LockModeType.PESSIMISTIC_WRITE) on an object, the entity manager must ensure that dirty read nor non-repeatable read occurs.

If transaction calls lock(entity, LockModeType.PESSIMISTIC_FORCE_INCREMENT) on a versioned object, the entity manager must ensure that dirty read nor non-repeatable read occurs and must also force an update (increment) to the entity's version column.


4.     API to use
There are multiple APIs to specify locking an Entity: 
1.     EntityManager methods: lock, find, refresh
2.     Query methods: setLockMode 
3.     NamedQuery annotation: lockMode element 


No comments:

Post a Comment