We have encountered an issue after upgrading to Spring Boot 3. We observed that our Gradle build started selecting spring-jdbc version 6.X instead of the previous 5.X version. This change led to an unexpected behavior related to exception handling in our application.

Specifically, we noticed that JDBC exceptions were being thrown directly, instead of being translated into DataAccessExceptions as they were previously. Upon investigating the source code, we identified that the SQLErrorCodeSQLExceptionTranslator is only instantiated under the following condition:

if (SQLErrorCodeSQLExceptionTranslator.hasUserProvidedErrorCodesFile()) {
    exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(obtainDataSource());
}

This condition checks for the presence of a user-provided error codes file:

private static final boolean userProvidedErrorCodesFilePresent =
        new ClassPathResource(SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH,
                SQLErrorCodesFactory.class.getClassLoader()).exists();

with SQL_ERROR_CODE_OVERRIDE_PATH defined as:

public static final String SQL_ERROR_CODE_OVERRIDE_PATH = "sql-error-codes.xml";

After manually adding the sql-error-codes.xml file to the root of our project, the exceptions were translated as expected. This leads to my question:

  • Is this change in behavior intentional? I could not find any documentation regarding this modification. The presence of the default error definitions file in spring-jdbc:
public static final String SQL_ERROR_CODE_DEFAULT_PATH = "org/springframework/jdbc/support/sql-error-codes.xml";

makes me think that this behavior might not be intentional. The default behavior in version 5.X did not require manual intervention for exception translation to function correctly.

Thanks!

Comment From: jhoeller

This is intentional, as mentioned in the upgrade notes: https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x

We are phasing out our hand-crafted default error codes file for JDBC 4 SQLException subclass translation with a few extra checks, as implemented in SQLExceptionSubclassTranslator which serves as our default now.

If there are any specific error codes that you care about there (not covered by SQLException subclasses and our existing checks) which we could specifically check in SQLExceptionSubclassTranslator, feel free to create an enhancement request for those.