Spring Transaction provides comprehensive exception hierarchies for transaction failures and data access issues. All exceptions are unchecked (runtime exceptions), allowing for optional handling while maintaining clean code.
Root exception for all transaction-related failures.
/**
* Superclass for all transaction exceptions.
* Base exception for the transaction infrastructure.
*/
public abstract class TransactionException extends NestedRuntimeException {
public TransactionException(String msg);
public TransactionException(String msg, Throwable cause);
}/**
* Exception thrown when a transaction cannot be created.
*/
public class CannotCreateTransactionException extends TransactionException {
public CannotCreateTransactionException(String msg);
public CannotCreateTransactionException(String msg, Throwable cause);
}
/**
* Exception thrown when a transaction has completed with an unknown outcome
* due to a heuristic decision by the transaction coordinator.
*/
public class HeuristicCompletionException extends TransactionException {
public static final int STATE_UNKNOWN = 0;
public static final int STATE_COMMITTED = 1;
public static final int STATE_ROLLED_BACK = 2;
public static final int STATE_MIXED = 3;
public HeuristicCompletionException(int outcomeState, Throwable cause);
public int getOutcomeState();
}
/**
* Exception thrown when an operation is attempted that relies on
* an existing transaction and none is present.
*/
public class NoTransactionException extends TransactionException {
public NoTransactionException(String msg);
public NoTransactionException(String msg, Throwable cause);
}
/**
* Exception thrown when an attempt is made to work with a nested transaction
* but nested transactions are not supported by the underlying backend.
*/
public class NestedTransactionNotSupportedException extends CannotCreateTransactionException {
public NestedTransactionNotSupportedException(String msg);
public NestedTransactionNotSupportedException(String msg, Throwable cause);
}
/**
* Exception thrown when the existence of or participation in an existing
* transaction is illegal, e.g. when using PROPAGATION_NEVER.
*/
public class IllegalTransactionStateException extends TransactionException {
public IllegalTransactionStateException(String msg);
public IllegalTransactionStateException(String msg, Throwable cause);
}
/**
* Exception thrown when attempting to use an invalid isolation level.
*/
public class InvalidIsolationLevelException extends TransactionException {
public InvalidIsolationLevelException(String msg);
}
/**
* Exception thrown when an invalid timeout value is specified.
*/
public class InvalidTimeoutException extends TransactionException {
public InvalidTimeoutException(String msg, int timeout);
}
/**
* Exception thrown when an attempt to suspend or resume a transaction fails.
*/
public class TransactionSuspensionNotSupportedException extends CannotCreateTransactionException {
public TransactionSuspensionNotSupportedException(String msg);
public TransactionSuspensionNotSupportedException(String msg, Throwable cause);
}
/**
* Exception thrown when a general transaction system error is encountered.
*/
public class TransactionSystemException extends TransactionException {
public TransactionSystemException(String msg);
public TransactionSystemException(String msg, Throwable cause);
}
/**
* Exception thrown when a transaction has timed out.
*/
public class TransactionTimedOutException extends TransactionException {
public TransactionTimedOutException(String msg);
public TransactionTimedOutException(String msg, Throwable cause);
}
/**
* Superclass for exceptions caused by inappropriate transaction usage.
*/
public class TransactionUsageException extends TransactionException {
public TransactionUsageException(String msg);
public TransactionUsageException(String msg, Throwable cause);
}
/**
* Exception thrown when a commit operation encounters an unexpected
* rollback decision from the transaction coordinator.
*/
public class UnexpectedRollbackException extends TransactionException {
public UnexpectedRollbackException(String msg);
public UnexpectedRollbackException(String msg, Throwable cause);
}Root exception for data access issues. Provides a technology-agnostic exception hierarchy.
/**
* Root of the hierarchy of data access exceptions.
* Serves as the superclass for all data access exceptions thrown by the Spring framework.
*/
public abstract class DataAccessException extends NestedRuntimeException {
public DataAccessException(String msg);
public DataAccessException(String msg, Throwable cause);
}Exceptions for temporary failures where retry may succeed.
/**
* Root for exceptions where a retry of the same operation might succeed.
*/
public abstract class TransientDataAccessException extends DataAccessException {
public TransientDataAccessException(String msg);
public TransientDataAccessException(String msg, Throwable cause);
}
/**
* Exception thrown on concurrency failure.
* Base class for optimistic and pessimistic locking failures.
*/
public class ConcurrencyFailureException extends TransientDataAccessException {
public ConcurrencyFailureException(String msg);
public ConcurrencyFailureException(String msg, Throwable cause);
}
/**
* Exception thrown on an optimistic locking violation.
* Indicates that an update failed due to a concurrent modification.
*/
public class OptimisticLockingFailureException extends ConcurrencyFailureException {
public OptimisticLockingFailureException(String msg);
public OptimisticLockingFailureException(String msg, Throwable cause);
}
/**
* Exception thrown on a pessimistic locking violation.
*/
public class PessimisticLockingFailureException extends ConcurrencyFailureException {
public PessimisticLockingFailureException(String msg);
public PessimisticLockingFailureException(String msg, Throwable cause);
}
/**
* Exception thrown when an attempt to acquire a lock fails.
*/
public class CannotAcquireLockException extends PessimisticLockingFailureException {
public CannotAcquireLockException(String msg);
public CannotAcquireLockException(String msg, Throwable cause);
}
/**
* Exception thrown when a transaction cannot be serialized.
*/
public class CannotSerializeTransactionException extends PessimisticLockingFailureException {
public CannotSerializeTransactionException(String msg);
public CannotSerializeTransactionException(String msg, Throwable cause);
}
/**
* Exception thrown when a transaction loses in a deadlock.
*/
public class DeadlockLoserDataAccessException extends PessimisticLockingFailureException {
public DeadlockLoserDataAccessException(String msg, Throwable cause);
}
/**
* Exception thrown when a query times out.
*/
public class QueryTimeoutException extends TransientDataAccessException {
public QueryTimeoutException(String msg);
public QueryTimeoutException(String msg, Throwable cause);
}
/**
* Exception thrown when a resource temporarily fails.
*/
public class TransientDataAccessResourceException extends TransientDataAccessException {
public TransientDataAccessResourceException(String msg);
public TransientDataAccessResourceException(String msg, Throwable cause);
}
/**
* Exception thrown for recoverable data access failures.
*/
public class RecoverableDataAccessException extends DataAccessException {
public RecoverableDataAccessException(String msg);
public RecoverableDataAccessException(String msg, Throwable cause);
}Exceptions for permanent failures where retry won't help.
/**
* Root for exceptions where a retry would fail unless the cause is corrected.
*/
public abstract class NonTransientDataAccessException extends DataAccessException {
public NonTransientDataAccessException(String msg);
public NonTransientDataAccessException(String msg, Throwable cause);
}
/**
* Exception thrown when an attempt to insert or update data violates an integrity constraint.
*/
public class DataIntegrityViolationException extends NonTransientDataAccessException {
public DataIntegrityViolationException(String msg);
public DataIntegrityViolationException(String msg, Throwable cause);
}
/**
* Exception thrown when an attempt to insert or update data results in a duplicate key.
*/
public class DuplicateKeyException extends DataIntegrityViolationException {
public DuplicateKeyException(String msg);
public DuplicateKeyException(String msg, Throwable cause);
}
/**
* Exception thrown when data cannot be retrieved.
*/
public class DataRetrievalFailureException extends NonTransientDataAccessException {
public DataRetrievalFailureException(String msg);
public DataRetrievalFailureException(String msg, Throwable cause);
}
/**
* Exception thrown when a result was not of the expected size.
*/
public class IncorrectResultSizeDataAccessException extends DataRetrievalFailureException {
public IncorrectResultSizeDataAccessException(int expectedSize);
public IncorrectResultSizeDataAccessException(int expectedSize, int actualSize);
public IncorrectResultSizeDataAccessException(String msg, int expectedSize);
public IncorrectResultSizeDataAccessException(String msg, int expectedSize, int actualSize);
public int getExpectedSize();
public int getActualSize();
}
/**
* Exception thrown when a result was expected but none was actually found.
*/
public class EmptyResultDataAccessException extends IncorrectResultSizeDataAccessException {
public EmptyResultDataAccessException(int expectedSize);
public EmptyResultDataAccessException(String msg, int expectedSize);
}
/**
* Exception thrown on incorrect usage of the data access API.
*/
public class InvalidDataAccessApiUsageException extends NonTransientDataAccessException {
public InvalidDataAccessApiUsageException(String msg);
public InvalidDataAccessApiUsageException(String msg, Throwable cause);
}
/**
* Exception thrown when SQL or other data access resources are used incorrectly.
*/
public class InvalidDataAccessResourceUsageException extends NonTransientDataAccessException {
public InvalidDataAccessResourceUsageException(String msg);
public InvalidDataAccessResourceUsageException(String msg, Throwable cause);
}
/**
* Exception thrown when an update operation is performed with incorrect semantics.
*/
public class IncorrectUpdateSemanticsDataAccessException
extends InvalidDataAccessResourceUsageException {
public IncorrectUpdateSemanticsDataAccessException(String msg);
public IncorrectUpdateSemanticsDataAccessException(String msg, Throwable cause);
public boolean wasDataUpdated();
}
/**
* Exception thrown when a type mismatch occurs in data access operations.
*/
public class TypeMismatchDataAccessException extends InvalidDataAccessResourceUsageException {
public TypeMismatchDataAccessException(String msg);
public TypeMismatchDataAccessException(String msg, Throwable cause);
}
/**
* Exception thrown when a data access operation is denied.
*/
public class PermissionDeniedDataAccessException extends NonTransientDataAccessException {
public PermissionDeniedDataAccessException(String msg, Throwable cause);
}
/**
* Exception thrown when cleanup operations fail.
*/
public class CleanupFailureDataAccessException extends NonTransientDataAccessException {
public CleanupFailureDataAccessException(String msg, Throwable cause);
}
/**
* Exception thrown when a data access resource non-transiently fails.
*/
public class NonTransientDataAccessResourceException extends NonTransientDataAccessException {
public NonTransientDataAccessResourceException(String msg);
public NonTransientDataAccessResourceException(String msg, Throwable cause);
}
/**
* Exception thrown when a resource fails.
*/
public class DataAccessResourceFailureException extends NonTransientDataAccessResourceException {
public DataAccessResourceFailureException(String msg);
public DataAccessResourceFailureException(String msg, Throwable cause);
}
/**
* Exception thrown when we can't classify a data access exception into a more specific one.
*/
public abstract class UncategorizedDataAccessException extends NonTransientDataAccessException {
public UncategorizedDataAccessException(String msg, Throwable cause);
}Strategy interface for translating persistence exceptions to Spring's DataAccessException hierarchy.
/**
* Strategy interface for translating between persistence exceptions and
* Spring's generic DataAccessException hierarchy.
*/
public interface PersistenceExceptionTranslator {
/**
* Translate the given exception if possible.
* Returns null if the exception cannot be translated.
*/
DataAccessException translateExceptionIfPossible(RuntimeException ex);
}@Service
public class OrderService {
@Transactional
public void createOrder(Order order) {
try {
orderRepository.save(order);
} catch (DataIntegrityViolationException e) {
// Handle constraint violation
throw new BusinessException("Order already exists", e);
} catch (OptimisticLockingFailureException e) {
// Handle concurrent modification
throw new BusinessException("Order was modified by another user", e);
}
}
}@Service
public class RetryableService {
public void processWithRetry(Order order) {
int maxRetries = 3;
for (int i = 0; i < maxRetries; i++) {
try {
processOrder(order);
return; // Success
} catch (TransientDataAccessException e) {
if (i == maxRetries - 1) {
throw new BusinessException("Failed after retries", e);
}
// Wait before retry
Thread.sleep(100 * (i + 1));
}
}
}
}@Service
public class TransactionExceptionService {
public void handleTransactionExceptions() {
try {
performTransactionalOperation();
} catch (CannotCreateTransactionException e) {
// Transaction system unavailable
logger.error("Cannot create transaction", e);
} catch (TransactionTimedOutException e) {
// Transaction took too long
logger.warn("Transaction timeout", e);
} catch (UnexpectedRollbackException e) {
// Transaction was marked for rollback
logger.error("Unexpected rollback", e);
} catch (TransactionException e) {
// Generic transaction failure
logger.error("Transaction failed", e);
}
}
}@Service
public class DataAccessService {
public User findRequiredUser(Long id) {
try {
return userRepository.findById(id)
.orElseThrow(() -> new EmptyResultDataAccessException(1));
} catch (EmptyResultDataAccessException e) {
throw new UserNotFoundException("User not found: " + id);
}
}
public void createUser(User user) {
try {
userRepository.save(user);
} catch (DuplicateKeyException e) {
throw new BusinessException("User with email already exists");
} catch (DataIntegrityViolationException e) {
throw new BusinessException("Invalid user data", e);
}
}
}TransactionException is the root for transaction infrastructure failuresDataAccessException is the root for data access failuresTransientDataAccessException indicates retry may succeedNonTransientDataAccessException indicates permanent failure