-
Bug
-
Resolution: Done
-
Major
-
None
added a check for roll-back-only condition, however, we should first check for active JTA transaction. The reason is that when Hibernate ORM calls accessTransaction().getRollbackOnly(), an ISE exception is immediately thrown by org.hibernate.engine.transaction.internal.TransactionImpl.getRollbackOnly, which is confusing to users, as they called EntityManager.find(), which shouldn't throw "IllegalStateException: JPA compliance dictates throwing IllegalStateException when #getRollbackOnly is called on non-active transaction", as the application didn't call #getRollbackOnly.
I suggest a change from:
public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockModeType, Map<String, Object> properties) {
checkOpen();
LockOptions lockOptions = null;
try {
getLoadQueryInfluencers().getEffectiveEntityGraph().applyConfiguredGraph( properties );
final IdentifierLoadAccess<T> loadAccess = byId( entityClass );
loadAccess.with( determineAppropriateLocalCacheMode( properties ) );
if ( lockModeType != null ) {
if ( !LockModeType.NONE.equals( lockModeType) ) {
checkTransactionNeededForUpdateOperation();
}
lockOptions = buildLockOptions( lockModeType, properties );
loadAccess.with( lockOptions );
}
return loadAccess.load( (Serializable) primaryKey );
}
catch ( EntityNotFoundException ignored ) {
// DefaultLoadEventListener.returnNarrowedProxy may throw ENFE (see HHH-7861 for details),
// which find() should not throw. Find() should return null if the entity was not found.
if ( log.isDebugEnabled() ) {
String entityName = entityClass != null ? entityClass.getName(): null;
String identifierValue = primaryKey != null ? primaryKey.toString() : null ;
log.ignoringEntityNotFound( entityName, identifierValue );
}
return null;
}
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 | TypeMismatchException | ClassCastException e ) {
throw exceptionConverter.convert( new IllegalArgumentException( e.getMessage(), e ) );
}
catch ( JDBCException e ) {
if ( accessTransaction().getRollbackOnly() ) {
// assume this is the similar to the WildFly / IronJacamar "feature" described under HHH-12472
return null;
}
else {
throw exceptionConverter.convert( e, lockOptions );
}
}
catch ( RuntimeException e ) {
throw exceptionConverter.convert( e, lockOptions );
}
finally {
getLoadQueryInfluencers().getEffectiveEntityGraph().clear();
}
}
Change instead to:
public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockModeType, Map<String, Object> properties) {
checkOpen();
LockOptions lockOptions = null;
try {
getLoadQueryInfluencers().getEffectiveEntityGraph().applyConfiguredGraph( properties );
final IdentifierLoadAccess<T> loadAccess = byId( entityClass );
loadAccess.with( determineAppropriateLocalCacheMode( properties ) );
if ( lockModeType != null ) {
if ( !LockModeType.NONE.equals( lockModeType) ) {
checkTransactionNeededForUpdateOperation();
}
lockOptions = buildLockOptions( lockModeType, properties );
loadAccess.with( lockOptions );
}
return loadAccess.load( (Serializable) primaryKey );
}
catch ( EntityNotFoundException ignored ) {
// DefaultLoadEventListener.returnNarrowedProxy may throw ENFE (see HHH-7861 for details),
// which find() should not throw. Find() should return null if the entity was not found.
if ( log.isDebugEnabled() ) {
String entityName = entityClass != null ? entityClass.getName(): null;
String identifierValue = primaryKey != null ? primaryKey.toString() : null ;
log.ignoringEntityNotFound( entityName, identifierValue );
}
return null;
}
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 | TypeMismatchException | ClassCastException e ) {
throw exceptionConverter.convert( new IllegalArgumentException( e.getMessage(), e ) );
}
catch ( JDBCException e ) {
// Note one line change is below.
if ( accessTransaction().isActive() && accessTransaction().getRollbackOnly() && accessTransaction().getRollbackOnly() ) {
// assume this is the similar to the WildFly / IronJacamar "feature" described under HHH-12472
return null;
}
else {
throw exceptionConverter.convert( e, lockOptions );
}
}
catch ( RuntimeException e ) {
throw exceptionConverter.convert( e, lockOptions );
}
finally {
getLoadQueryInfluencers().getEffectiveEntityGraph().clear();
}
}
I'll try the above change locally and check if the current ORM testsuite still passes (on ORM master branch).
- is incorporated by
-
JBEAP-17963 [GSS](7.2.z) Upgrade Hibernate ORM from 5.3.14.Final-redhat-00001 to 5.3.15.Final-redhat-00001
-
- Closed
-
- incorporates
-
HHH-13433 Loading...