Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "EclipseLink/Development/JPA 2.0/pessimistic locking"
(→Internal execution) |
(→lock(Object, LockModeType)) |
||
Line 156: | Line 156: | ||
#If the PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type is specified and the javax.persistence.lock.timeout is also specified, a javax.persistence.LockTimeoutException will be thrown if an exception is raised when issuing the locking query. If no timeout hint is specified a javax,persistence.PessimisticLockException will be thrown. | #If the PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type is specified and the javax.persistence.lock.timeout is also specified, a javax.persistence.LockTimeoutException will be thrown if an exception is raised when issuing the locking query. If no timeout hint is specified a javax,persistence.PessimisticLockException will be thrown. | ||
#Whenever a pessimistic lock is used on an entity that contains a version attribute, that attribute will be updated (incremented) | #Whenever a pessimistic lock is used on an entity that contains a version attribute, that attribute will be updated (incremented) | ||
+ | |||
+ | ===== Internal execution ===== | ||
+ | EclipseLink will use the descriptor's defined query to avoid extra query creation if it exists, | ||
+ | <pre>ReadObjectQuery query = descriptor.getQueryManager().getReadObjectQuery(); | ||
+ | query.checkPrepare((AbstractSession) session, null); | ||
+ | query = (ReadObjectQuery) query.clone(); | ||
+ | </pre> | ||
+ | |||
+ | Otherwise a new query will create be created: | ||
+ | |||
+ | <pre> | ||
+ | ReadObjectQuery query = new ReadObjectQuery(); | ||
+ | query.setReferenceClass(referenceClass); | ||
+ | </pre> | ||
+ | |||
+ | Followed with the following internal settings and returns the execution of the query result. | ||
+ | |||
+ | <pre> | ||
+ | query.setIsExecutionClone(true); | ||
+ | query.setSelectionKey(primaryKeyValues); | ||
+ | query.conformResultsInUnitOfWork(); | ||
+ | |||
+ | // If the LockModeType is null or NONE | ||
+ | query.setLockMode(ObjectBuildingQuery.NO_LOCK); | ||
+ | return uow.executeQuery(query); | ||
+ | |||
+ | // If the LockModeType is PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT | ||
+ | |||
+ | // If the javax.persistence.lock.timeout value has been specified in the EntityManager properties. | ||
+ | query.setLockMode(ObjectBuildingQuery.LOCK) | ||
+ | query.setQueryTimeout(javax.persistence.lock.timeout value); | ||
+ | return uow.executeQuery(query); | ||
+ | |||
+ | // Otherwise a no wait lock mode is set. | ||
+ | query.setLockMode(ObjectBuildingQuery.LOCK_NOWAIT); | ||
+ | return uow.executeQuery(query); | ||
+ | |||
+ | // If the LockModeType is READ, WRITE, OPTIMISTIC, OPTIMISTIC_FORCE_INCREMENT | ||
+ | Result object = uow.executeQuery(query); | ||
+ | uow.forceUpdateToVersionField(obj, (lockMode == WRITE || lockMode == OPTIMISTIC_FORCE_INCREMENT)); | ||
+ | return obj; | ||
+ | </pre> | ||
+ | |||
+ | Note: The only property/query hint that can be applied in this case is the javax.persistence.lock.timeout | ||
====lock(Object, LockModeType, Map)==== | ====lock(Object, LockModeType, Map)==== |
Revision as of 13:28, 17 October 2008
Contents
- 1 Lock Modes / Pessimistic Locking
- 1.1 Issue Summary
- 1.2 General Solution
- 1.3 Usage matrix
- 1.3.1 EntityManager
- 1.3.1.1 find(Class<T>, Object)
- 1.3.1.2 find(Class<T>, Object, LockModeType)
- 1.3.1.3 find(Class<T>, Object, LockModeType, Map)
- 1.3.1.4 lock(Object, LockModeType)
- 1.3.1.5 lock(Object, LockModeType, Map)
- 1.3.1.6 refresh(Object)
- 1.3.1.7 refresh(Object, LockModeType)
- 1.3.1.8 refresh(Object, LockModeType, Map)
- 1.3.2 Query Interface
- 1.3.1 EntityManager
- 1.4 Important Notes
- 1.5 Work Required
Lock Modes / Pessimistic Locking
JPA 2.0 Root | Enhancement Request
Issue Summary
In JPA 2.0 the specification extends Entity Manager lock mechanism to include explicit support for pessimistic locking. EntityManager and Query APIs have been updated with an additional query hint/persistence unit property. The specification has extensive detail on expected behaviour that must be implemented.
See JPA 2.0 ED section 3.4.3, 3.4.4, 3.6.3 and 3.6.4 for details.
General Solution
As EclipseLink includes Pessimistic Locking functionality this feature should be limited to comprehensive implementation of the JPA functionality and behaviour without many core changes. Pessimistic Locking and Optimistic Locking LockModesTypes must be covered, new query hint/persistence unit timeout properties and new Exceptions must be supported. As well, current query and Entity operations support must be updated to comply with new Pessimistic locking constraints.
Open Issues
Will Target table mappings (uni-directional OneToMany, ElementCollections) require that target rows also be locked?
Usage matrix
EntityManager
find(Class<T>, Object)
- Uses no locking
- Will NOT use a javax.persistence.lock.timeout setting from the EntityManager settings as it does not apply in this case where no pessimistic locking is available.
Internal execution
EclipseLink will use the descriptor's defined query to avoid extra query creation if it exists,
ReadObjectQuery query = descriptor.getQueryManager().getReadObjectQuery(); query.checkPrepare((AbstractSession) session, null); query = (ReadObjectQuery) query.clone();
Otherwise a new query will create be created:
ReadObjectQuery query = new ReadObjectQuery(); query.setReferenceClass(referenceClass);
Followed with the following internal settings and returns the execution of the query result.
query.setLockMode(ObjectBuildingQuery.NO_LOCK); query.setIsExecutionClone(true); query.setSelectionKey(primaryKeyValues); query.conformResultsInUnitOfWork(); return uow.executeQuery(query);
Note: There are no properties or query hints to apply in this case.
find(Class<T>, Object, LockModeType)
- Uses the lock mode specified
- A javax.persistence.lock.timeout setting from the EntityManager settings will be used if available on the find query (internally it will set the query timeout value)
- If the PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type is specified and the javax.persistence.lock.timeout is specified, a javax.persistence.LockTimeoutException will be thrown if an exception is raised when issuing the locking query. If no timeout hint is specified a javax,persistence.PessimisticLockException will be thrown.
- Whenever a pessimistic lock is used on an entity that contains a version attribute, that attribute will be updated (incremented)
Internal execution
EclipseLink will use the descriptor's defined query to avoid extra query creation if it exists,
ReadObjectQuery query = descriptor.getQueryManager().getReadObjectQuery(); query.checkPrepare((AbstractSession) session, null); query = (ReadObjectQuery) query.clone();
Otherwise a new query will create be created:
ReadObjectQuery query = new ReadObjectQuery(); query.setReferenceClass(referenceClass);
Followed with the following internal settings and returns the execution of the query result.
query.setIsExecutionClone(true); query.setSelectionKey(primaryKeyValues); query.conformResultsInUnitOfWork(); // If the LockModeType is null or NONE query.setLockMode(ObjectBuildingQuery.NO_LOCK); return uow.executeQuery(query); // If the LockModeType is PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT // If the javax.persistence.lock.timeout value has been specified in the EntityManager properties. query.setLockMode(ObjectBuildingQuery.LOCK) query.setQueryTimeout(javax.persistence.lock.timeout value); return uow.executeQuery(query); // Otherwise a no wait lock mode is set. query.setLockMode(ObjectBuildingQuery.LOCK_NOWAIT); return uow.executeQuery(query); // If the LockModeType is READ, WRITE, OPTIMISTIC, OPTIMISTIC_FORCE_INCREMENT Result object = uow.executeQuery(query); uow.forceUpdateToVersionField(obj, (lockMode == WRITE || lockMode == OPTIMISTIC_FORCE_INCREMENT)); return obj;
Note: The only property/query hint that can be applied in this case is the javax.persistence.lock.timeout
find(Class<T>, Object, LockModeType, Map)
- Uses the lock mode specified
- A javax.persistence.lock.timeout setting from the EntityManager settings will be not be used as it is assumed that the properties that are passed in are the strict set to be used with the find query.
- If the PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type is specified and the javax.persistence.lock.timeout or eclipselink.jdbc.timeout hint is specified, a javax.persistence.LockTimeoutException will be thrown if an exception is raised when issuing the find query. If no timeout hint is specified a javax,persistence.PessimisticLockException will be thrown.
- Whenever a pessimistic lock is used on an entity that contains a version attribute, that attribute will be updated (incremented)
Internal execution
EclipseLink will use the descriptor's defined query to avoid extra query creation if it exists,
ReadObjectQuery query = descriptor.getQueryManager().getReadObjectQuery(); query.checkPrepare((AbstractSession) session, null); query = (ReadObjectQuery) query.clone();
Otherwise a new query will create be created:
ReadObjectQuery query = new ReadObjectQuery(); query.setReferenceClass(referenceClass);
Followed with the following internal settings and returns the execution of the query result.
query.setIsExecutionClone(true); query.setSelectionKey(primaryKeyValues); // Apply the properties/query hints. QueryHintsHandler.apply(properties, query); // If the eclipselink.cache-usage hint is NOT set in the properties that are passed in, then query.conformResultsInUnitOfWork(); // If the LockModeType is null or NONE query.setLockMode(ObjectBuildingQuery.NO_LOCK); return uow.executeQuery(query); // If the LockModeType is PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT // If the javax.persistence.lock.timeout hint or the eclipselink.jdbc.timeout hint has been specified in the properties. query.setLockMode(ObjectBuildingQuery.LOCK) query.setQueryTimeout(javax.persistence.lock.timeout value || eclipselink.jdbc.timeout); return uow.executeQuery(query); // Otherwise a no wait lock mode is set. query.setLockMode(ObjectBuildingQuery.LOCK_NOWAIT); return uow.executeQuery(query); // If the LockModeType is READ, WRITE, OPTIMISTIC, OPTIMISTIC_FORCE_INCREMENT Result object = uow.executeQuery(query); uow.forceUpdateToVersionField(obj, (lockMode == WRITE || lockMode == OPTIMISTIC_FORCE_INCREMENT)); return obj;
Note: See org.eclipse.persistence.internal.jpa.QueryHintsHandler for the full list of available query hints that may be applied in this case.
lock(Object, LockModeType)
- Uses the lock mode specified
- A javax.persistence.lock.timeout setting from the EntityManager settings will be used if available on the lock query (internally it will set the query timeout value)
- If the PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type is specified and the javax.persistence.lock.timeout is also specified, a javax.persistence.LockTimeoutException will be thrown if an exception is raised when issuing the locking query. If no timeout hint is specified a javax,persistence.PessimisticLockException will be thrown.
- Whenever a pessimistic lock is used on an entity that contains a version attribute, that attribute will be updated (incremented)
Internal execution
EclipseLink will use the descriptor's defined query to avoid extra query creation if it exists,
ReadObjectQuery query = descriptor.getQueryManager().getReadObjectQuery(); query.checkPrepare((AbstractSession) session, null); query = (ReadObjectQuery) query.clone();
Otherwise a new query will create be created:
ReadObjectQuery query = new ReadObjectQuery(); query.setReferenceClass(referenceClass);
Followed with the following internal settings and returns the execution of the query result.
query.setIsExecutionClone(true); query.setSelectionKey(primaryKeyValues); query.conformResultsInUnitOfWork(); // If the LockModeType is null or NONE query.setLockMode(ObjectBuildingQuery.NO_LOCK); return uow.executeQuery(query); // If the LockModeType is PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT // If the javax.persistence.lock.timeout value has been specified in the EntityManager properties. query.setLockMode(ObjectBuildingQuery.LOCK) query.setQueryTimeout(javax.persistence.lock.timeout value); return uow.executeQuery(query); // Otherwise a no wait lock mode is set. query.setLockMode(ObjectBuildingQuery.LOCK_NOWAIT); return uow.executeQuery(query); // If the LockModeType is READ, WRITE, OPTIMISTIC, OPTIMISTIC_FORCE_INCREMENT Result object = uow.executeQuery(query); uow.forceUpdateToVersionField(obj, (lockMode == WRITE || lockMode == OPTIMISTIC_FORCE_INCREMENT)); return obj;
Note: The only property/query hint that can be applied in this case is the javax.persistence.lock.timeout
lock(Object, LockModeType, Map)
- Uses the lock mode specified
- A javax.persistence.lock.timeout setting from the EntityManager settings will be not be used as it is assumed that the properties that are passed in are the strict set to be used with the find query.
- If the PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type is specified and the javax.persistence.lock.timeout or eclipselink.jdbc.timeout hint is also specified, a javax.persistence.LockTimeoutException will be thrown if an exception is raised when issuing the locking query. If no timeout hint is specified a javax,persistence.PessimisticLockException will be thrown.
- Whenever a pessimistic lock is used on an entity that contains a version attribute, that attribute will be updated (incremented)
refresh(Object)
- Uses no locking
- Will NOT use a javax.persistence.lock.timeout setting from the EntityManager settings as it does not apply in this case where no pessimistic locking is available.
- If the PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type is specified and the javax.persistence.lock.timeout is also specified, a javax.persistence.LockTimeoutException will be thrown if an exception is raised when issuing the locking query. If no timeout hint is specified a javax,persistence.PessimisticLockException will be thrown.
refresh(Object, LockModeType)
- Uses the lock mode specified
- A javax.persistence.lock.timeout setting from the EntityManager settings will be used if available on the find query (internally it will set the query timeout value)
- If the PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type is specified and the javax.persistence.lock.timeout is also specified, a javax.persistence.LockTimeoutException will be thrown if an exception is raised when issuing the refresh query. If no timeout hint is specified a javax,persistence.PessimisticLockException will be thrown.
refresh(Object, LockModeType, Map)
- Uses the lock mode specified
- A javax.persistence.lock.timeout setting from the EntityManager settings will be not be used as it is assumed that the properties that are passed in are the strict set to be used with the find query.
- If the PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type is specified as and the javax.persistence.lock.timeout or eclipselink.jdbc.timeout hint is also specified, a javax.persistence.LockTimeoutException will be thrown if an exception is raised when issuing the refresh query. If no timeout hint is specified a javax,persistence.PessimisticLockException will be thrown.#A javax.persistence.lock.timeout setting from the EntityManager settings will be not be used as it is assumed that the properties that are passed in are the strict set to be used with the find query.
Query Interface
JPA queries now accept a lock mode type through the use of the following API:
Query.setLockMode(LockModeType)
- The query will then issue the necessary lock when either getResultList(), getResultCollection() or getSingleResult() is executed.
- Calling setLockMode on an invalid query type will cause an IllegalStateException to be thrown
Query.setHint(String, Object)
A query lock timeout may also be used in conjunction with the lock mode (or by itself) using the following API:
Query.setHint("javax.persistence.lock.timeout", 5)
- When the lock timeout hint is used in conjunction with a PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type, a javax.persistence.LockTimeoutException will be thrown if the locking fails.
- If no lock timeout hint is used in conjunction with a PESSIMISTIC or PESSIMISTIC_FORCE_INCREMENT lock mode type, then a javax.persistence.PessimisticException will be thrown if the locking fails.
- When the lock timeout hint is used with any other lock mode type, a QueryTimeoutException will be thrown if the execution of the query takes longer the time out value.
Important Notes
- A considerable amount of behaviour definition will be found in the java docs of the EntityManger and Query APIs
- for instance upon issuing a pessimistic lock call on find if the version from the database does not match that of the persistence context then an exception must be raised
Work Required
- Develop tests for testing access type settings
- approx 3 days
- Update Processing to process entire table
- approx 2 days - optimistic modes
- approx 4 days - pessimistic modes