diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java index 44b8838b210..f82e8475ce1 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,11 +26,15 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * Base class for {@link SQLExceptionTranslator} implementations that allow for - * fallback to some other {@link SQLExceptionTranslator}. + * Base class for {@link SQLExceptionTranslator} implementations that allow for a + * fallback to some other {@link SQLExceptionTranslator}, as well as for custom + * overrides. * * @author Juergen Hoeller * @since 2.5.6 + * @see #doTranslate + * @see #setFallbackTranslator + * @see #setCustomTranslator */ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExceptionTranslator { @@ -40,10 +44,13 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep @Nullable private SQLExceptionTranslator fallbackTranslator; + @Nullable + private SQLExceptionTranslator customTranslator; + /** - * Override the default SQL state fallback translator - * (typically a {@link SQLStateSQLExceptionTranslator}). + * Set the fallback translator to use when this translator cannot find a + * specific match itself. */ public void setFallbackTranslator(@Nullable SQLExceptionTranslator fallback) { this.fallbackTranslator = fallback; @@ -51,12 +58,33 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep /** * Return the fallback exception translator, if any. + * @see #setFallbackTranslator */ @Nullable public SQLExceptionTranslator getFallbackTranslator() { return this.fallbackTranslator; } + /** + * Set a custom exception translator to override any match that this translator + * would find. Note that such a custom {@link SQLExceptionTranslator} delegate + * is meant to return {@code null} if it does not have an override itself. + * @since 6.1 + */ + public void setCustomTranslator(@Nullable SQLExceptionTranslator customTranslator) { + this.customTranslator = customTranslator; + } + + /** + * Return a custom exception translator, if any. + * @since 6.1 + * @see #setCustomTranslator + */ + @Nullable + public SQLExceptionTranslator getCustomTranslator() { + return this.customTranslator; + } + /** * Pre-checks the arguments, calls {@link #doTranslate}, and invokes the @@ -67,6 +95,15 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep public DataAccessException translate(String task, @Nullable String sql, SQLException ex) { Assert.notNull(ex, "Cannot translate a null SQLException"); + SQLExceptionTranslator custom = getCustomTranslator(); + if (custom != null) { + DataAccessException dae = custom.translate(task, sql, ex); + if (dae != null) { + // Custom exception match found. + return dae; + } + } + DataAccessException dae = doTranslate(task, sql, ex); if (dae != null) { // Specific exception match found. diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java index 25d1513a782..16c8c092fbc 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java @@ -60,6 +60,11 @@ import org.springframework.util.function.SupplierUtils; * of the class path (e.g. in the "/WEB-INF/classes" directory), as long as the * Spring JDBC package is loaded from the same ClassLoader. * + *
This translator is commonly used by default if a user-provided `sql-error-codes.xml`
+ * file has been found in the root of the classpath, as a signal to use this strategy.
+ * Otherwise, {@link SQLExceptionSubclassTranslator} serves as the default translator
+ * as of 6.0.
+ *
* @author Rod Johnson
* @author Thomas Risberg
* @author Juergen Hoeller
@@ -75,11 +80,10 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
private static final int MESSAGE_SQL_THROWABLE_CONSTRUCTOR = 4;
private static final int MESSAGE_SQL_SQLEX_CONSTRUCTOR = 5;
- private static final boolean USER_PROVIDED_ERROR_CODES_FILE_PRESENT =
- new ClassPathResource(SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH, SQLErrorCodesFactory.class.getClassLoader()).exists();
-
+ private static final boolean userProvidedErrorCodesFilePresent =
+ new ClassPathResource(SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH,
+ SQLErrorCodesFactory.class.getClassLoader()).exists();
- /** Error codes used by this translator. */
@Nullable
private SingletonSupplier