[HHH-12472] 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: {code} 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(); } } {code}
Change instead to: {code} 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(); } } {code}
I'll try the above change locally and check if the current ORM testsuite still passes (on ORM master branch). |
|