]
Bryan Varner commented on HHH-7252:
-----------------------------------
I'm having a bit of a problem with my test case. Creating this test case has exposed
that the situation I had with HHH-7251 also exists for the H2 dialect, and likely nearly
every other Dialect Hibernate supports.
So I'm sort of at am impasse here. Do I fail the test and then try to update all the
Dialects under HHH-7251, or do I log the exception like was already done in the
hibernate-entitymanager LockTest.java? (which seems wrong, since the exception should have
been properly identified and handled, and the rollback semantics are drastically different
for LockTimeoutException vs. PessimisticLockException and PersistenceException)
Either way, this is feeling down right ugly.
Thoughts?
EntityManager not retaining LockOptions context when mapping
exceptions.
------------------------------------------------------------------------
Key: HHH-7252
URL:
https://hibernate.onjira.com/browse/HHH-7252
Project: Hibernate ORM
Issue Type: Bug
Components: entity-manager
Affects Versions: 4.1.2
Environment: PostgreSQL 9.1
Reporter: Bryan Varner
Priority: Critical
Original Estimate: 5m
Remaining Estimate: 5m
AbstractEntityManagerImpl.java:791 (Implementation of EntityManager.find())
This line defines a local LockOptions and sets it to null.
A conditional execution for including lock options on line 795 evaluates the LockOptions
but never sets it back to the local.
When an exception occurs (lock timeout, or otherwise) the lockOptions have not been set
to anything but null, and incorrect exceptions are resolved and thrown.
Specifically, you get PessimisticLockException even when you should get
LockTimeoutException.
This is marking transactions as rollback only, and causing subsequent code to fail
gloriously.
Below is the offensive function, notice that lockOptions is never set to anything other
than =null.
{code}
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType
lockModeType, Map<String, Object> properties) {
CacheMode previousCacheMode = getSession().getCacheMode();
CacheMode cacheMode = determineAppropriateLocalCacheMode( properties );
LockOptions lockOptions = null;
try {
getSession().setCacheMode( cacheMode );
if ( lockModeType != null ) {
return ( A ) getSession().get(
entityClass, ( Serializable ) primaryKey,
getLockRequest( lockModeType, properties )
);
}
else {
return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey );
}
}
catch ( ObjectDeletedException e ) {
//the spec is silent about people doing remove() find() on the same PC
return null;
}
catch ( ObjectNotFoundException e ) {
//should not happen on the entity itself with get
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( MappingException e ) {
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( TypeMismatchException e ) {
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( ClassCastException e ) {
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( HibernateException he ) {
throw convert( he, lockOptions );
}
finally {
getSession().setCacheMode( previousCacheMode );
}
}
{code}
--
This message is automatically generated by JIRA.
For more information on JIRA, see: