Merge branch '6.0.x'
# Conflicts: # spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java
This commit is contained in:
commit
fd17df91fd
|
|
@ -380,6 +380,12 @@ Notice that the methods to be scheduled must have void returns and must not acce
|
||||||
arguments. If the method needs to interact with other objects from the application
|
arguments. If the method needs to interact with other objects from the application
|
||||||
context, those would typically have been provided through dependency injection.
|
context, those would typically have been provided through dependency injection.
|
||||||
|
|
||||||
|
`@Scheduled` can be used as a repeatable annotation. If several scheduled declarations
|
||||||
|
are found on the same method, each of them will be processed independently, with a
|
||||||
|
separate trigger firing for each of them. As a consequence, such co-located schedules
|
||||||
|
may overlap and execute multiple times in parallel or in immediate succession.
|
||||||
|
Please make sure that your specified cron expressions etc do not accidentally overlap.
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
As of Spring Framework 4.3, `@Scheduled` methods are supported on beans of any scope.
|
As of Spring Framework 4.3, `@Scheduled` methods are supported on beans of any scope.
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation that marks a method to be scheduled. Exactly one of the
|
* Annotation that marks a method to be scheduled. Exactly one of the
|
||||||
* {@link #cron}, {@link #fixedDelay}, or {@link #fixedRate} attributes must be
|
* {@link #cron}, {@link #fixedDelay}, or {@link #fixedRate} attributes
|
||||||
* specified.
|
* must be specified.
|
||||||
*
|
*
|
||||||
* <p>The annotated method must not accept arguments. It will typically have
|
* <p>The annotated method must not accept arguments. It will typically have
|
||||||
* a {@code void} return type; if not, the returned value will be ignored
|
* a {@code void} return type; if not, the returned value will be ignored
|
||||||
|
|
@ -56,7 +56,10 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||||
* or {@link EnableScheduling @EnableScheduling} annotation.
|
* or {@link EnableScheduling @EnableScheduling} annotation.
|
||||||
*
|
*
|
||||||
* <p>This annotation can be used as a <em>{@linkplain Repeatable repeatable}</em>
|
* <p>This annotation can be used as a <em>{@linkplain Repeatable repeatable}</em>
|
||||||
* annotation.
|
* annotation. If several scheduled declarations are found on the same method,
|
||||||
|
* each of them will be processed independently, with a separate trigger firing
|
||||||
|
* for each of them. As a consequence, such co-located schedules may overlap
|
||||||
|
* and execute multiple times in parallel or in immediate succession.
|
||||||
*
|
*
|
||||||
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
|
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
|
||||||
* <em>composed annotations</em> with attribute overrides.
|
* <em>composed annotations</em> with attribute overrides.
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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…
Reference in New Issue