Browse Source

Polishing

pull/30915/head
Juergen Hoeller 2 years ago
parent
commit
384246c360
  1. 36
      spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java
  2. 9
      spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java
  3. 25
      spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java
  4. 36
      spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcTransactionManager.java
  5. 27
      spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java
  6. 6
      spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java
  7. 19
      spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslator.java

36
spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java

@ -354,7 +354,7 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
exporter.setBeans(beansToExport); exporter.setBeans(beansToExport);
exporter.setServer(getServer()); exporter.setServer(getServer());
exporter.setBeanFactory(factory); exporter.setBeanFactory(factory);
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_NONE); exporter.setAutodetect(false);
// MBean has a bad ObjectName, so if said MBean is autodetected, an exception will be thrown... // MBean has a bad ObjectName, so if said MBean is autodetected, an exception will be thrown...
start(exporter); start(exporter);
} }
@ -524,18 +524,16 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
} }
@Test @Test
void notRunningInBeanFactoryAndPassedBeanNameToExport() throws Exception { void notRunningInBeanFactoryAndPassedBeanNameToExport() {
Map<String, Object> beans = Map.of(OBJECT_NAME, "beanName"); Map<String, Object> beans = Map.of(OBJECT_NAME, "beanName");
exporter.setBeans(beans); exporter.setBeans(beans);
assertThatExceptionOfType(MBeanExportException.class) assertThatExceptionOfType(MBeanExportException.class).isThrownBy(() -> start(exporter));
.isThrownBy(() -> start(exporter));
} }
@Test @Test
void notRunningInBeanFactoryAndAutodetectionIsOn() throws Exception { void notRunningInBeanFactoryAndAutodetectionIsOn() {
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL); exporter.setAutodetect(true);
assertThatExceptionOfType(MBeanExportException.class) assertThatExceptionOfType(MBeanExportException.class).isThrownBy(() -> start(exporter));
.isThrownBy(() -> start(exporter));
} }
@Test // SPR-2158 @Test // SPR-2158
@ -556,7 +554,7 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
} }
@Test // SPR-3302 @Test // SPR-3302
void beanNameCanBeUsedInNotificationListenersMap() throws Exception { void beanNameCanBeUsedInNotificationListenersMap() {
String beanName = "charlesDexterWard"; String beanName = "charlesDexterWard";
BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class); BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class);
@ -576,7 +574,7 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
} }
@Test @Test
void wildcardCanBeUsedInNotificationListenersMap() throws Exception { void wildcardCanBeUsedInNotificationListenersMap() {
String beanName = "charlesDexterWard"; String beanName = "charlesDexterWard";
BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class); BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class);
@ -636,24 +634,23 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
exporter.setServer(getServer()); exporter.setServer(getServer());
exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(firstBeanName, secondBeanName)); exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(firstBeanName, secondBeanName));
exporter.setBeanFactory(factory); exporter.setBeanFactory(factory);
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL); exporter.setAutodetect(true);
exporter.addExcludedBean(secondBeanName); exporter.addExcludedBean(secondBeanName);
start(exporter); start(exporter);
assertIsRegistered("Bean not autodetected in (AUTODETECT_ALL) mode", assertIsRegistered("Bean not autodetected", ObjectNameManager.getInstance(firstBeanName));
ObjectNameManager.getInstance(firstBeanName)); assertIsNotRegistered("Bean should have been excluded", ObjectNameManager.getInstance(secondBeanName));
assertIsNotRegistered("Bean should have been excluded",
ObjectNameManager.getInstance(secondBeanName));
} }
@Test @Test
void registerFactoryBean() throws MalformedObjectNameException { void registerFactoryBean() throws MalformedObjectNameException {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition("spring:type=FactoryBean", new RootBeanDefinition(ProperSomethingFactoryBean.class)); factory.registerBeanDefinition("spring:type=FactoryBean",
new RootBeanDefinition(ProperSomethingFactoryBean.class));
exporter.setServer(getServer()); exporter.setServer(getServer());
exporter.setBeanFactory(factory); exporter.setBeanFactory(factory);
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL); exporter.setAutodetect(true);
start(exporter); start(exporter);
assertIsRegistered("Non-null FactoryBean object registered", assertIsRegistered("Non-null FactoryBean object registered",
@ -663,11 +660,12 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
@Test @Test
void ignoreNullObjectFromFactoryBean() throws MalformedObjectNameException { void ignoreNullObjectFromFactoryBean() throws MalformedObjectNameException {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition("spring:type=FactoryBean", new RootBeanDefinition(NullSomethingFactoryBean.class)); factory.registerBeanDefinition("spring:type=FactoryBean",
new RootBeanDefinition(NullSomethingFactoryBean.class));
exporter.setServer(getServer()); exporter.setServer(getServer());
exporter.setBeanFactory(factory); exporter.setBeanFactory(factory);
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL); exporter.setAutodetect(true);
start(exporter); start(exporter);
assertIsNotRegistered("Null FactoryBean object not registered", assertIsNotRegistered("Null FactoryBean object not registered",

9
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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,6 +31,8 @@ import org.springframework.util.Assert;
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.5.6 * @since 2.5.6
* @see #doTranslate
* @see #setFallbackTranslator
*/ */
public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExceptionTranslator { public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExceptionTranslator {
@ -42,8 +44,8 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
/** /**
* Override the default SQL state fallback translator * Set the fallback translator to use when this translator cannot find a
* (typically a {@link SQLStateSQLExceptionTranslator}). * specific match itself.
*/ */
public void setFallbackTranslator(@Nullable SQLExceptionTranslator fallback) { public void setFallbackTranslator(@Nullable SQLExceptionTranslator fallback) {
this.fallbackTranslator = fallback; this.fallbackTranslator = fallback;
@ -51,6 +53,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
/** /**
* Return the fallback exception translator, if any. * Return the fallback exception translator, if any.
* @see #setFallbackTranslator
*/ */
@Nullable @Nullable
public SQLExceptionTranslator getFallbackTranslator() { public SQLExceptionTranslator getFallbackTranslator() {

25
spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -80,10 +80,11 @@ public abstract class JdbcAccessor implements InitializingBean {
} }
/** /**
* Specify the database product name for the DataSource that this accessor uses. * Specify the database product name for the {@code DataSource} that this accessor uses.
* This allows to initialize an SQLErrorCodeSQLExceptionTranslator without * This allows for initializing a {@link SQLErrorCodeSQLExceptionTranslator} without
* obtaining a Connection from the DataSource to get the meta-data. * obtaining a {@code Connection} from the {@code DataSource} to get the meta-data.
* @param dbName the database product name that identifies the error codes entry * @param dbName the database product name that identifies the error codes entry
* @see #setExceptionTranslator
* @see SQLErrorCodeSQLExceptionTranslator#setDatabaseProductName * @see SQLErrorCodeSQLExceptionTranslator#setDatabaseProductName
* @see java.sql.DatabaseMetaData#getDatabaseProductName() * @see java.sql.DatabaseMetaData#getDatabaseProductName()
*/ */
@ -98,22 +99,20 @@ public abstract class JdbcAccessor implements InitializingBean {
/** /**
* Set the exception translator for this instance. * Set the exception translator for this instance.
* <p>If no custom translator is provided, a default * <p>A {@link SQLErrorCodeSQLExceptionTranslator} used by default if a user-provided
* {@link SQLErrorCodeSQLExceptionTranslator} is used * `sql-error-codes.xml` file has been found in the root of the classpath. Otherwise,
* which examines the SQLException's vendor-specific error code. * {@link SQLExceptionSubclassTranslator} serves as the default translator as of 6.0.
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator * @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator * @see org.springframework.jdbc.support.SQLExceptionSubclassTranslator
*/ */
public void setExceptionTranslator(SQLExceptionTranslator exceptionTranslator) { public void setExceptionTranslator(SQLExceptionTranslator exceptionTranslator) {
this.exceptionTranslator = exceptionTranslator; this.exceptionTranslator = exceptionTranslator;
} }
/** /**
* Return the exception translator for this instance. * Return the exception translator to use for this instance,
* <p>Creates a default {@link SQLErrorCodeSQLExceptionTranslator} * creating a default if necessary.
* for the specified DataSource if none set, or a * @see #setExceptionTranslator
* {@link SQLStateSQLExceptionTranslator} in case of no DataSource.
* @see #getDataSource()
*/ */
public SQLExceptionTranslator getExceptionTranslator() { public SQLExceptionTranslator getExceptionTranslator() {
SQLExceptionTranslator exceptionTranslator = this.exceptionTranslator; SQLExceptionTranslator exceptionTranslator = this.exceptionTranslator;

36
spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcTransactionManager.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -59,8 +59,8 @@ public class JdbcTransactionManager extends DataSourceTransactionManager {
/** /**
* Create a new JdbcTransactionManager instance. * Create a new {@code JdbcTransactionManager} instance.
* A DataSource has to be set to be able to use it. * A {@code DataSource} has to be set to be able to use it.
* @see #setDataSource * @see #setDataSource
*/ */
public JdbcTransactionManager() { public JdbcTransactionManager() {
@ -68,7 +68,7 @@ public class JdbcTransactionManager extends DataSourceTransactionManager {
} }
/** /**
* Create a new JdbcTransactionManager instance. * Create a new {@code JdbcTransactionManager} instance.
* @param dataSource the JDBC DataSource to manage transactions for * @param dataSource the JDBC DataSource to manage transactions for
*/ */
public JdbcTransactionManager(DataSource dataSource) { public JdbcTransactionManager(DataSource dataSource) {
@ -79,13 +79,15 @@ public class JdbcTransactionManager extends DataSourceTransactionManager {
/** /**
* Specify the database product name for the DataSource that this transaction manager * Specify the database product name for the {@code DataSource} that this
* uses. This allows to initialize an SQLErrorCodeSQLExceptionTranslator without * transaction manager operates on.
* obtaining a Connection from the DataSource to get the meta-data. * This allows for initializing a {@link SQLErrorCodeSQLExceptionTranslator} without
* obtaining a {@code Connection} from the {@code DataSource} to get the meta-data.
* @param dbName the database product name that identifies the error codes entry * @param dbName the database product name that identifies the error codes entry
* @see JdbcAccessor#setDatabaseProductName * @see #setExceptionTranslator
* @see SQLErrorCodeSQLExceptionTranslator#setDatabaseProductName * @see SQLErrorCodeSQLExceptionTranslator#setDatabaseProductName
* @see java.sql.DatabaseMetaData#getDatabaseProductName() * @see java.sql.DatabaseMetaData#getDatabaseProductName()
* @see JdbcAccessor#setDatabaseProductName
*/ */
public void setDatabaseProductName(String dbName) { public void setDatabaseProductName(String dbName) {
if (SQLErrorCodeSQLExceptionTranslator.hasUserProvidedErrorCodesFile()) { if (SQLErrorCodeSQLExceptionTranslator.hasUserProvidedErrorCodesFile()) {
@ -97,22 +99,22 @@ public class JdbcTransactionManager extends DataSourceTransactionManager {
} }
/** /**
* Set the exception translator for this instance. * Set the exception translator for this transaction manager.
* <p>If no custom translator is provided, a default * <p>A {@link SQLErrorCodeSQLExceptionTranslator} used by default if a user-provided
* {@link SQLErrorCodeSQLExceptionTranslator} is used * `sql-error-codes.xml` file has been found in the root of the classpath. Otherwise,
* which examines the SQLException's vendor-specific error code. * {@link SQLExceptionSubclassTranslator} serves as the default translator as of 6.0.
* @see JdbcAccessor#setExceptionTranslator
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator * @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
* @see org.springframework.jdbc.support.SQLExceptionSubclassTranslator
* @see JdbcAccessor#setExceptionTranslator
*/ */
public void setExceptionTranslator(SQLExceptionTranslator exceptionTranslator) { public void setExceptionTranslator(SQLExceptionTranslator exceptionTranslator) {
this.exceptionTranslator = exceptionTranslator; this.exceptionTranslator = exceptionTranslator;
} }
/** /**
* Return the exception translator for this instance. * Return the exception translator to use for this instance,
* <p>Creates a default {@link SQLErrorCodeSQLExceptionTranslator} * creating a default if necessary.
* for the specified DataSource if none set. * @see #setExceptionTranslator
* @see #getDataSource()
*/ */
public SQLExceptionTranslator getExceptionTranslator() { public SQLExceptionTranslator getExceptionTranslator() {
SQLExceptionTranslator exceptionTranslator = this.exceptionTranslator; SQLExceptionTranslator exceptionTranslator = this.exceptionTranslator;

27
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 * 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. * Spring JDBC package is loaded from the same ClassLoader.
* *
* <p>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 Rod Johnson
* @author Thomas Risberg * @author Thomas Risberg
* @author Juergen Hoeller * @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_THROWABLE_CONSTRUCTOR = 4;
private static final int MESSAGE_SQL_SQLEX_CONSTRUCTOR = 5; private static final int MESSAGE_SQL_SQLEX_CONSTRUCTOR = 5;
private static final boolean USER_PROVIDED_ERROR_CODES_FILE_PRESENT = private static final boolean userProvidedErrorCodesFilePresent =
new ClassPathResource(SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH, SQLErrorCodesFactory.class.getClassLoader()).exists(); new ClassPathResource(SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH,
SQLErrorCodesFactory.class.getClassLoader()).exists();
/** Error codes used by this translator. */
@Nullable @Nullable
private SingletonSupplier<SQLErrorCodes> sqlErrorCodes; private SingletonSupplier<SQLErrorCodes> sqlErrorCodes;
@ -198,9 +202,9 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
if (sqlErrorCodes != null) { if (sqlErrorCodes != null) {
SQLExceptionTranslator customTranslator = sqlErrorCodes.getCustomSqlExceptionTranslator(); SQLExceptionTranslator customTranslator = sqlErrorCodes.getCustomSqlExceptionTranslator();
if (customTranslator != null) { if (customTranslator != null) {
DataAccessException customDex = customTranslator.translate(task, sql, sqlEx); dae = customTranslator.translate(task, sql, sqlEx);
if (customDex != null) { if (dae != null) {
return customDex; return dae;
} }
} }
} }
@ -228,11 +232,10 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
for (CustomSQLErrorCodesTranslation customTranslation : customTranslations) { for (CustomSQLErrorCodesTranslation customTranslation : customTranslations) {
if (Arrays.binarySearch(customTranslation.getErrorCodes(), errorCode) >= 0 && if (Arrays.binarySearch(customTranslation.getErrorCodes(), errorCode) >= 0 &&
customTranslation.getExceptionClass() != null) { customTranslation.getExceptionClass() != null) {
DataAccessException customException = createCustomException( dae = createCustomException(task, sql, sqlEx, customTranslation.getExceptionClass());
task, sql, sqlEx, customTranslation.getExceptionClass()); if (dae != null) {
if (customException != null) {
logTranslation(task, sql, sqlEx, true); logTranslation(task, sql, sqlEx, true);
return customException; return dae;
} }
} }
} }
@ -426,7 +429,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
* in the root of the classpath. * in the root of the classpath.
*/ */
static boolean hasUserProvidedErrorCodesFile() { static boolean hasUserProvidedErrorCodesFile() {
return USER_PROVIDED_ERROR_CODES_FILE_PRESENT; return userProvidedErrorCodesFilePresent;
} }
} }

6
spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -51,6 +51,8 @@ import org.springframework.lang.Nullable;
* <p>Falls back to a standard {@link SQLStateSQLExceptionTranslator} if the JDBC * <p>Falls back to a standard {@link SQLStateSQLExceptionTranslator} if the JDBC
* driver does not actually expose JDBC 4 compliant {@code SQLException} subclasses. * driver does not actually expose JDBC 4 compliant {@code SQLException} subclasses.
* *
* <p>This translator serves as the default translator as of 6.0.
*
* @author Thomas Risberg * @author Thomas Risberg
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.5 * @since 2.5
@ -72,7 +74,7 @@ public class SQLExceptionSubclassTranslator extends AbstractFallbackSQLException
return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex); return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex);
} }
if (ex instanceof SQLTransactionRollbackException) { if (ex instanceof SQLTransactionRollbackException) {
if ("40001".equals(ex.getSQLState())) { if (SQLStateSQLExceptionTranslator.indicatesCannotAcquireLock(ex.getSQLState())) {
return new CannotAcquireLockException(buildMessage(task, sql, ex), ex); return new CannotAcquireLockException(buildMessage(task, sql, ex), ex);
} }
return new PessimisticLockingFailureException(buildMessage(task, sql, ex), ex); return new PessimisticLockingFailureException(buildMessage(task, sql, ex), ex);

19
spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslator.java

@ -39,11 +39,16 @@ import org.springframework.lang.Nullable;
* does not require special initialization (no database vendor detection, etc.). * does not require special initialization (no database vendor detection, etc.).
* For more precise translation, consider {@link SQLErrorCodeSQLExceptionTranslator}. * For more precise translation, consider {@link SQLErrorCodeSQLExceptionTranslator}.
* *
* <p>This translator is commonly used as a {@link #setFallbackTranslator fallback}
* behind a primary translator such as {@link SQLErrorCodeSQLExceptionTranslator} or
* {@link SQLExceptionSubclassTranslator}.
*
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Thomas Risberg * @author Thomas Risberg
* @see java.sql.SQLException#getSQLState() * @see java.sql.SQLException#getSQLState()
* @see SQLErrorCodeSQLExceptionTranslator * @see SQLErrorCodeSQLExceptionTranslator
* @see SQLExceptionSubclassTranslator
*/ */
public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLExceptionTranslator { public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLExceptionTranslator {
@ -111,7 +116,7 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException
return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex); return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex);
} }
else if (PESSIMISTIC_LOCKING_FAILURE_CODES.contains(classCode)) { else if (PESSIMISTIC_LOCKING_FAILURE_CODES.contains(classCode)) {
if ("40001".equals(sqlState)) { if (indicatesCannotAcquireLock(sqlState)) {
return new CannotAcquireLockException(buildMessage(task, sql, ex), ex); return new CannotAcquireLockException(buildMessage(task, sql, ex), ex);
} }
return new PessimisticLockingFailureException(buildMessage(task, sql, ex), ex); return new PessimisticLockingFailureException(buildMessage(task, sql, ex), ex);
@ -148,9 +153,10 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException
return sqlState; return sqlState;
} }
/** /**
* Check whether the given SQL state (and the associated error code in case * Check whether the given SQL state (and the associated error code in case
* of a generic SQL state value) indicate a duplicate key exception: * of a generic SQL state value) indicate a {@link DuplicateKeyException}:
* either SQL state 23505 as a specific indication, or the generic SQL state * either SQL state 23505 as a specific indication, or the generic SQL state
* 23000 with well-known vendor codes (1 for Oracle, 1062 for MySQL/MariaDB, * 23000 with well-known vendor codes (1 for Oracle, 1062 for MySQL/MariaDB,
* 2601/2627 for MS SQL Server). * 2601/2627 for MS SQL Server).
@ -163,4 +169,13 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException
(errorCode == 1 || errorCode == 1062 || errorCode == 2601 || errorCode == 2627))); (errorCode == 1 || errorCode == 1062 || errorCode == 2601 || errorCode == 2627)));
} }
/**
* Check whether the given SQL state indicates a {@link CannotAcquireLockException},
* with SQL state 40001 as a specific indication.
* @param sqlState the SQL state value
*/
static boolean indicatesCannotAcquireLock(@Nullable String sqlState) {
return "40001".equals(sqlState);
}
} }

Loading…
Cancel
Save