Skip to content

Commit 083113d

Browse files
committed
Use SQLExceptionSubclassTranslator by default (avoiding sql-error-codes.xml)
SQLErrorCodeSQLExceptionTranslator kicks in for user-provided sql-error-codes.xml files. It will still pick up Spring's legacy default error code mappings as well but only when triggered by a (potentially empty) user-provided file in the root of the classpath. Closes gh-28216
1 parent 4e1b9f1 commit 083113d

File tree

5 files changed

+45
-38
lines changed

5 files changed

+45
-38
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import org.apache.commons.logging.LogFactory;
2323

2424
import org.springframework.beans.factory.InitializingBean;
25-
import org.springframework.core.SpringProperties;
2625
import org.springframework.lang.Nullable;
2726
import org.springframework.util.Assert;
2827

@@ -41,13 +40,6 @@
4140
*/
4241
public abstract class JdbcAccessor implements InitializingBean {
4342

44-
/**
45-
* Boolean flag controlled by a {@code spring.xml.ignore} system property that instructs Spring to
46-
* ignore XML, i.e. to not initialize the XML-related infrastructure.
47-
* <p>The default is "false".
48-
*/
49-
private static final boolean shouldIgnoreXml = SpringProperties.getFlag("spring.xml.ignore");
50-
5143
/** Logger available to subclasses. */
5244
protected final Log logger = LogFactory.getLog(getClass());
5345

@@ -96,9 +88,12 @@ protected DataSource obtainDataSource() {
9688
* @see java.sql.DatabaseMetaData#getDatabaseProductName()
9789
*/
9890
public void setDatabaseProductName(String dbName) {
99-
if (!shouldIgnoreXml) {
91+
if (SQLErrorCodeSQLExceptionTranslator.hasUserProvidedErrorCodesFile()) {
10092
this.exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dbName);
10193
}
94+
else {
95+
this.exceptionTranslator = new SQLExceptionSubclassTranslator();
96+
}
10297
}
10398

10499
/**
@@ -128,15 +123,11 @@ public SQLExceptionTranslator getExceptionTranslator() {
128123
synchronized (this) {
129124
exceptionTranslator = this.exceptionTranslator;
130125
if (exceptionTranslator == null) {
131-
DataSource dataSource = getDataSource();
132-
if (shouldIgnoreXml) {
133-
exceptionTranslator = new SQLExceptionSubclassTranslator();
134-
}
135-
else if (dataSource != null) {
136-
exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource);
126+
if (SQLErrorCodeSQLExceptionTranslator.hasUserProvidedErrorCodesFile()) {
127+
exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(obtainDataSource());
137128
}
138129
else {
139-
exceptionTranslator = new SQLStateSQLExceptionTranslator();
130+
exceptionTranslator = new SQLExceptionSubclassTranslator();
140131
}
141132
this.exceptionTranslator = exceptionTranslator;
142133
}

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

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@
2020

2121
import javax.sql.DataSource;
2222

23-
import org.springframework.core.SpringProperties;
2423
import org.springframework.dao.DataAccessException;
2524
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
2625
import org.springframework.lang.Nullable;
@@ -53,14 +52,6 @@
5352
@SuppressWarnings("serial")
5453
public class JdbcTransactionManager extends DataSourceTransactionManager {
5554

56-
/**
57-
* Boolean flag controlled by a {@code spring.xml.ignore} system property that instructs Spring to
58-
* ignore XML, i.e. to not initialize the XML-related infrastructure.
59-
* <p>The default is "false".
60-
*/
61-
private static final boolean shouldIgnoreXml = SpringProperties.getFlag("spring.xml.ignore");
62-
63-
6455
@Nullable
6556
private volatile SQLExceptionTranslator exceptionTranslator;
6657

@@ -97,9 +88,12 @@ public JdbcTransactionManager(DataSource dataSource) {
9788
* @see java.sql.DatabaseMetaData#getDatabaseProductName()
9889
*/
9990
public void setDatabaseProductName(String dbName) {
100-
if (!shouldIgnoreXml) {
91+
if (SQLErrorCodeSQLExceptionTranslator.hasUserProvidedErrorCodesFile()) {
10192
this.exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dbName);
10293
}
94+
else {
95+
this.exceptionTranslator = new SQLExceptionSubclassTranslator();
96+
}
10397
}
10498

10599
/**
@@ -128,11 +122,11 @@ public SQLExceptionTranslator getExceptionTranslator() {
128122
synchronized (this) {
129123
exceptionTranslator = this.exceptionTranslator;
130124
if (exceptionTranslator == null) {
131-
if (shouldIgnoreXml) {
132-
exceptionTranslator = new SQLExceptionSubclassTranslator();
125+
if (SQLErrorCodeSQLExceptionTranslator.hasUserProvidedErrorCodesFile()) {
126+
exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(obtainDataSource());
133127
}
134128
else {
135-
exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(obtainDataSource());
129+
exceptionTranslator = new SQLExceptionSubclassTranslator();
136130
}
137131
this.exceptionTranslator = exceptionTranslator;
138132
}

spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import javax.sql.DataSource;
2525

26+
import org.springframework.core.io.ClassPathResource;
2627
import org.springframework.dao.CannotAcquireLockException;
2728
import org.springframework.dao.CannotSerializeTransactionException;
2829
import org.springframework.dao.DataAccessException;
@@ -417,4 +418,14 @@ private void logTranslation(String task, @Nullable String sql, SQLException sqlE
417418
}
418419
}
419420

421+
422+
/**
423+
* Check whether there is a user-provided `sql-error-codes.xml` file
424+
* in the root of the classpath.
425+
*/
426+
static boolean hasUserProvidedErrorCodesFile() {
427+
return new ClassPathResource(SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH,
428+
SQLErrorCodesFactory.class.getClassLoader()).exists();
429+
}
430+
420431
}

spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
2828
import org.springframework.beans.BeansException;
2929
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
3030
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
31+
import org.springframework.core.SpringProperties;
3132
import org.springframework.core.io.ClassPathResource;
3233
import org.springframework.core.io.Resource;
3334
import org.springframework.lang.Nullable;
@@ -66,6 +67,13 @@ public class SQLErrorCodesFactory {
6667

6768
private static final Log logger = LogFactory.getLog(SQLErrorCodesFactory.class);
6869

70+
/**
71+
* Boolean flag controlled by a {@code spring.xml.ignore} system property that instructs Spring to
72+
* ignore XML, i.e. to not initialize the XML-related infrastructure.
73+
* <p>The default is "false".
74+
*/
75+
private static final boolean shouldIgnoreXml = SpringProperties.getFlag("spring.xml.ignore");
76+
6977
/**
7078
* Keep track of a single instance so we can return it to classes that request it.
7179
*/
@@ -101,6 +109,10 @@ public static SQLErrorCodesFactory getInstance() {
101109
* @see #loadResource(String)
102110
*/
103111
protected SQLErrorCodesFactory() {
112+
if (shouldIgnoreXml) {
113+
throw new UnsupportedOperationException("XML support disabled");
114+
}
115+
104116
Map<String, SQLErrorCodes> errorCodes;
105117

106118
try {

spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTests.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,8 @@ public void testSQLErrorCodeTranslation() throws Exception {
944944
mockDatabaseMetaData(false);
945945
given(this.connection.createStatement()).willReturn(this.preparedStatement);
946946

947+
this.template.setExceptionTranslator(new SQLErrorCodeSQLExceptionTranslator(this.dataSource));
948+
947949
assertThatExceptionOfType(BadSqlGrammarException.class).isThrownBy(() ->
948950
this.template.query(sql, (RowCallbackHandler) rs -> {
949951
throw sqlException;
@@ -955,20 +957,17 @@ public void testSQLErrorCodeTranslation() throws Exception {
955957
}
956958

957959
@Test
958-
public void testSQLErrorCodeTranslationWithSpecifiedDbName() throws Exception {
960+
public void testSQLErrorCodeTranslationWithSpecifiedDatabaseName() throws Exception {
959961
final SQLException sqlException = new SQLException("I have a known problem", "99999", 1054);
960962
final String sql = "SELECT ID FROM CUSTOMER";
961963

962964
given(this.resultSet.next()).willReturn(true);
963965
given(this.connection.createStatement()).willReturn(this.preparedStatement);
964966

965-
JdbcTemplate template = new JdbcTemplate();
966-
template.setDataSource(this.dataSource);
967-
template.setDatabaseProductName("MySQL");
968-
template.afterPropertiesSet();
967+
this.template.setExceptionTranslator(new SQLErrorCodeSQLExceptionTranslator("MySQL"));
969968

970969
assertThatExceptionOfType(BadSqlGrammarException.class).isThrownBy(() ->
971-
template.query(sql, (RowCallbackHandler) rs -> {
970+
this.template.query(sql, (RowCallbackHandler) rs -> {
972971
throw sqlException;
973972
}))
974973
.withCause(sqlException);
@@ -983,7 +982,7 @@ public void testSQLErrorCodeTranslationWithSpecifiedDbName() throws Exception {
983982
* to get the metadata
984983
*/
985984
@Test
986-
public void testUseCustomSQLErrorCodeTranslator() throws Exception {
985+
public void testUseCustomExceptionTranslator() throws Exception {
987986
// Bad SQL state
988987
final SQLException sqlException = new SQLException("I have a known problem", "07000", 1054);
989988
final String sql = "SELECT ID FROM CUSTOMER";

0 commit comments

Comments
 (0)