clean up ExceptionConverterImpl

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-09-01 15:32:29 +02:00
parent dd16ed61f0
commit d7aa5f7a78
3 changed files with 50 additions and 78 deletions

View File

@ -11,7 +11,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.TransactionException; import org.hibernate.TransactionException;
import org.hibernate.engine.spi.ExceptionConverter;
import org.hibernate.engine.transaction.spi.TransactionImplementor; import org.hibernate.engine.transaction.spi.TransactionImplementor;
import org.hibernate.internal.AbstractSharedSessionContract; import org.hibernate.internal.AbstractSharedSessionContract;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;

View File

@ -46,12 +46,12 @@ import jakarta.persistence.RollbackException;
public class ExceptionConverterImpl implements ExceptionConverter { public class ExceptionConverterImpl implements ExceptionConverter {
private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( ExceptionConverterImpl.class ); private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( ExceptionConverterImpl.class );
private final SharedSessionContractImplementor sharedSessionContract; private final SharedSessionContractImplementor session;
private final boolean isJpaBootstrap; private final boolean isJpaBootstrap;
public ExceptionConverterImpl(SharedSessionContractImplementor sharedSessionContract) { public ExceptionConverterImpl(SharedSessionContractImplementor session) {
this.sharedSessionContract = sharedSessionContract; this.session = session;
isJpaBootstrap = sharedSessionContract.getFactory().getSessionFactoryOptions().isJpaBootstrap(); isJpaBootstrap = session.getFactory().getSessionFactoryOptions().isJpaBootstrap();
} }
@Override @Override
@ -59,30 +59,15 @@ public class ExceptionConverterImpl implements ExceptionConverter {
if ( isJpaBootstrap ) { if ( isJpaBootstrap ) {
try { try {
//as per the spec we should roll back if commit fails //as per the spec we should roll back if commit fails
sharedSessionContract.getTransaction().rollback(); session.getTransaction().rollback();
} }
catch (Exception re) { catch (Exception re) {
//swallow //swallow
} }
return new RollbackException( "Error while committing the transaction", wrapCommitException( exception ) ); return new RollbackException( "Error while committing the transaction",
} exception instanceof HibernateException hibernateException
else { ? convert( hibernateException )
return exception; : exception );
}
}
private Throwable wrapCommitException(RuntimeException exception) {
if ( exception instanceof HibernateException ) {
return convert( (HibernateException) exception);
}
else if ( exception instanceof PersistenceException ) {
Throwable cause = exception.getCause() == null ? exception : exception.getCause();
if ( cause instanceof HibernateException ) {
return convert( (HibernateException) cause );
}
else {
return cause;
}
} }
else { else {
return exception; return exception;
@ -147,7 +132,7 @@ public class ExceptionConverterImpl implements ExceptionConverter {
} }
else if ( exception instanceof TransientObjectException ) { else if ( exception instanceof TransientObjectException ) {
try { try {
sharedSessionContract.markForRollbackOnly(); session.markForRollbackOnly();
} }
catch (Exception ne) { catch (Exception ne) {
//we do not want the subsequent exception to swallow the original one //we do not want the subsequent exception to swallow the original one
@ -169,99 +154,78 @@ public class ExceptionConverterImpl implements ExceptionConverter {
@Override @Override
public RuntimeException convert(RuntimeException exception) { public RuntimeException convert(RuntimeException exception) {
if ( exception instanceof HibernateException ) { if ( exception instanceof HibernateException hibernateException ) {
return convert( (HibernateException) exception ); return convert( hibernateException );
} }
else { else {
sharedSessionContract.markForRollbackOnly(); session.markForRollbackOnly();
return exception; return exception;
} }
} }
@Override @Override
public RuntimeException convert(RuntimeException exception, LockOptions lockOptions) { public RuntimeException convert(RuntimeException exception, LockOptions lockOptions) {
if ( exception instanceof HibernateException ) { if ( exception instanceof HibernateException hibernateException ) {
return convert( (HibernateException) exception, lockOptions ); return convert( hibernateException, lockOptions );
} }
else { else {
sharedSessionContract.markForRollbackOnly(); session.markForRollbackOnly();
return exception; return exception;
} }
} }
@Override @Override
public JDBCException convert(SQLException e, String message) { public JDBCException convert(SQLException e, String message) {
return sharedSessionContract.getJdbcServices().getSqlExceptionHelper().convert( e, message ); return session.getJdbcServices().getSqlExceptionHelper().convert( e, message );
} }
protected PersistenceException wrapStaleStateException(StaleStateException exception) { protected PersistenceException wrapStaleStateException(StaleStateException exception) {
if ( exception instanceof StaleObjectStateException ) { if ( exception instanceof StaleObjectStateException staleStateException ) {
final StaleObjectStateException sose = (StaleObjectStateException) exception; final Object identifier = staleStateException.getIdentifier();
final Object identifier = sose.getIdentifier(); final String entityName = staleStateException.getEntityName();
if ( identifier != null ) { if ( identifier != null ) {
try { try {
final Object entity = sharedSessionContract.internalLoad( sose.getEntityName(), identifier, false, true); final Object entity = session.internalLoad( entityName, identifier, false, true );
if ( entity instanceof Serializable ) { if ( entity instanceof Serializable ) { // avoid some user errors regarding boundary crossing
//avoid some user errors regarding boundary crossing
return new OptimisticLockException( exception.getMessage(), exception, entity ); return new OptimisticLockException( exception.getMessage(), exception, entity );
} }
else {
return new OptimisticLockException( exception.getMessage(), exception );
}
} }
catch (EntityNotFoundException enfe) { catch (EntityNotFoundException entityNotFoundException) {
return new OptimisticLockException( exception.getMessage(), exception ); // swallow it;
} }
} }
else {
return new OptimisticLockException( exception.getMessage(), exception );
}
}
else {
return new OptimisticLockException( exception.getMessage(), exception );
} }
return new OptimisticLockException( exception.getMessage(), exception );
} }
protected PersistenceException wrapLockException(HibernateException exception, LockOptions lockOptions) { protected PersistenceException wrapLockException(HibernateException exception, LockOptions lockOptions) {
if ( exception instanceof OptimisticEntityLockException ) { if ( exception instanceof OptimisticEntityLockException lockException ) {
final OptimisticEntityLockException lockException = (OptimisticEntityLockException) exception;
return new OptimisticLockException( lockException.getMessage(), lockException, lockException.getEntity() ); return new OptimisticLockException( lockException.getMessage(), lockException, lockException.getEntity() );
} }
else if ( exception instanceof org.hibernate.exception.LockTimeoutException ) { else if ( exception instanceof org.hibernate.exception.LockTimeoutException ) {
return new LockTimeoutException( exception.getMessage(), exception, null ); return new LockTimeoutException( exception.getMessage(), exception, null );
} }
else if ( exception instanceof PessimisticEntityLockException ) { else if ( exception instanceof PessimisticEntityLockException lockException ) {
final PessimisticEntityLockException lockException = (PessimisticEntityLockException) exception; // assume lock timeout occurred if a timeout or NO WAIT was specified
if ( lockOptions != null && lockOptions.getTimeOut() > -1 ) { return lockOptions != null && lockOptions.getTimeOut() > -1
// assume lock timeout occurred if a timeout or NO WAIT was specified ? new LockTimeoutException( lockException.getMessage(), lockException, lockException.getEntity() )
return new LockTimeoutException( lockException.getMessage(), lockException, lockException.getEntity() ); : new PessimisticLockException( lockException.getMessage(), lockException, lockException.getEntity() );
}
else {
return new PessimisticLockException( lockException.getMessage(), lockException, lockException.getEntity() );
}
} }
else if ( exception instanceof org.hibernate.PessimisticLockException ) { else if ( exception instanceof org.hibernate.PessimisticLockException lockException ) {
final org.hibernate.PessimisticLockException lockException = (org.hibernate.PessimisticLockException) exception; // assume lock timeout occurred if a timeout or NO WAIT was specified
if ( lockOptions != null && lockOptions.getTimeOut() > -1 ) { return lockOptions != null && lockOptions.getTimeOut() > -1
// assume lock timeout occurred if a timeout or NO WAIT was specified ? new LockTimeoutException( lockException.getMessage(), lockException, null )
return new LockTimeoutException( lockException.getMessage(), lockException, null ); : new PessimisticLockException( lockException.getMessage(), lockException, null );
}
else {
return new PessimisticLockException( lockException.getMessage(), lockException, null );
}
} }
else { else {
return new OptimisticLockException( exception ); return new OptimisticLockException( exception );
} }
} }
private void rollbackIfNecessary(PersistenceException e) { private void rollbackIfNecessary(PersistenceException persistenceException) {
if ( !( e instanceof NoResultException if ( !isNonRollbackException( persistenceException ) ) {
|| e instanceof NonUniqueResultException
|| e instanceof LockTimeoutException
|| e instanceof QueryTimeoutException ) ) {
try { try {
sharedSessionContract.markForRollbackOnly(); session.markForRollbackOnly();
} }
catch (Exception ne) { catch (Exception ne) {
//we do not want the subsequent exception to swallow the original one //we do not want the subsequent exception to swallow the original one
@ -270,4 +234,15 @@ public class ExceptionConverterImpl implements ExceptionConverter {
} }
} }
/**
* Is this a special exception type explicitly exempted from
* forced rollbacks by the JPA specification itself?
*/
private static boolean isNonRollbackException(PersistenceException persistenceException) {
return persistenceException instanceof NoResultException
|| persistenceException instanceof NonUniqueResultException
|| persistenceException instanceof LockTimeoutException
|| persistenceException instanceof QueryTimeoutException;
}
} }

View File

@ -11,8 +11,6 @@ import org.jboss.logging.Logger;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
/** /**
* Sad when you need helpers for generating loggers...
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class HEMLogging { public class HEMLogging {