Check well-known database error codes in case of generic SQL state 23000

Closes gh-29699
This commit is contained in:
Juergen Hoeller
2022-12-23 15:13:29 +01:00
parent 697292ba0c
commit a644245e0e
6 changed files with 66 additions and 4 deletions

View File

@@ -231,7 +231,7 @@ public abstract class ConnectionFactoryUtils {
return new DataAccessResourceFailureException(buildMessage(task, sql, ex), ex);
}
if (ex instanceof R2dbcDataIntegrityViolationException) {
if ("23505".equals(ex.getSqlState())) {
if (indicatesDuplicateKey(ex.getSqlState(), ex.getErrorCode())) {
return new DuplicateKeyException(buildMessage(task, sql, ex), ex);
}
return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex);
@@ -246,6 +246,19 @@ public abstract class ConnectionFactoryUtils {
return new UncategorizedR2dbcException(buildMessage(task, sql, ex), sql, ex);
}
/**
* Check whether the given SQL state (and the associated error code in case
* of a generic SQL state value) indicate a duplicate key exception. See
* {@code org.springframework.jdbc.support.SQLStateSQLExceptionTranslator#indicatesDuplicateKey}.
* @param sqlState the SQL state value
* @param errorCode the error code value
*/
static boolean indicatesDuplicateKey(@Nullable String sqlState, int errorCode) {
return ("23505".equals(sqlState) ||
("23000".equals(sqlState) &&
(errorCode == 1 || errorCode == 1062 || errorCode == 2627)));
}
/**
* Build a message {@code String} for the given {@link R2dbcException}.
* <p>To be called by translator subclasses when creating an instance of a generic

View File

@@ -95,6 +95,18 @@ public class ConnectionFactoryUtilsUnitTests {
exception = ConnectionFactoryUtils.convertR2dbcException("", "",
new R2dbcDataIntegrityViolationException("reason", "23505"));
assertThat(exception).isExactlyInstanceOf(DuplicateKeyException.class);
exception = ConnectionFactoryUtils.convertR2dbcException("", "",
new R2dbcDataIntegrityViolationException("reason", "23000", 1));
assertThat(exception).isExactlyInstanceOf(DuplicateKeyException.class);
exception = ConnectionFactoryUtils.convertR2dbcException("", "",
new R2dbcDataIntegrityViolationException("reason", "23000", 1062));
assertThat(exception).isExactlyInstanceOf(DuplicateKeyException.class);
exception = ConnectionFactoryUtils.convertR2dbcException("", "",
new R2dbcDataIntegrityViolationException("reason", "23000", 2627));
assertThat(exception).isExactlyInstanceOf(DuplicateKeyException.class);
}
@Test