Skip to content

Commit 61b57f2

Browse files
author
trisberg
committed
added the option of providing a database specific custom SQLExceptionTranslator to provide customized translation for any SQLException before the error codes translation happens (SPR-4899 backport)
1 parent f5ec3fc commit 61b57f2

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

src/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,17 @@ protected DataAccessException doTranslate(String task, String sql, SQLException
187187
return dex;
188188
}
189189

190+
// Next, try the custom SQLException translator, if available.
191+
if (this.sqlErrorCodes != null) {
192+
SQLExceptionTranslator customTranslator = this.sqlErrorCodes.getCustomSqlExceptionTranslator();
193+
if (customTranslator != null) {
194+
DataAccessException customDex = customTranslator.translate(task, sql, sqlEx);
195+
if (customDex != null) {
196+
return customDex;
197+
}
198+
}
199+
}
200+
190201
// Check SQLErrorCodes with corresponding error code, if available.
191202
if (this.sqlErrorCodes != null) {
192203
String errorCode = null;

src/org/springframework/jdbc/support/SQLErrorCodes.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public class SQLErrorCodes {
3838

3939
private boolean useSqlStateForTranslation = false;
4040

41+
private SQLExceptionTranslator customSqlExceptionTranslator = null;
42+
4143
private String[] badSqlGrammarCodes = new String[0];
4244

4345
private String[] invalidResultSetAccessCodes = new String[0];
@@ -97,6 +99,27 @@ public boolean isUseSqlStateForTranslation() {
9799
return this.useSqlStateForTranslation;
98100
}
99101

102+
public SQLExceptionTranslator getCustomSqlExceptionTranslator() {
103+
return customSqlExceptionTranslator;
104+
}
105+
106+
public void setCustomSqlExceptionTranslatorClass(Class customSqlExceptionTranslatorClass) {
107+
if (customSqlExceptionTranslatorClass != null) {
108+
try {
109+
this.customSqlExceptionTranslator =
110+
(SQLExceptionTranslator) customSqlExceptionTranslatorClass.newInstance();
111+
}
112+
catch (InstantiationException e) {
113+
throw new InvalidDataAccessResourceUsageException(
114+
"Unable to instantiate " + customSqlExceptionTranslatorClass.getName(), e);
115+
}
116+
catch (IllegalAccessException e) {
117+
throw new InvalidDataAccessResourceUsageException(
118+
"Unable to instantiate " + customSqlExceptionTranslatorClass.getName(), e);
119+
}
120+
}
121+
}
122+
100123
public void setBadSqlGrammarCodes(String[] badSqlGrammarCodes) {
101124
this.badSqlGrammarCodes = StringUtils.sortStringArray(badSqlGrammarCodes);
102125
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2002-2009 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.jdbc.support;
18+
19+
import org.springframework.dao.DataAccessException;
20+
import org.springframework.dao.TransientDataAccessResourceException;
21+
22+
import java.sql.SQLException;
23+
24+
/**
25+
* Custom SQLException translation for testing.
26+
*
27+
* @author Thomas Risberg
28+
*/
29+
public class CustomSqlExceptionTranslator implements SQLExceptionTranslator {
30+
public DataAccessException translate(String task, String sql, SQLException ex) {
31+
if (ex.getErrorCode() == 2) {
32+
return new TransientDataAccessResourceException("Custom", ex);
33+
}
34+
return null;
35+
}
36+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2002-2008 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.jdbc.support;
18+
19+
import org.springframework.dao.DataAccessException;
20+
import org.springframework.dao.TransientDataAccessResourceException;
21+
import org.springframework.jdbc.BadSqlGrammarException;
22+
23+
import java.sql.SQLException;
24+
25+
import junit.framework.TestCase;
26+
27+
/**
28+
* Class to test custom SQLException translation.
29+
*
30+
* @author Thomas Risberg
31+
*/
32+
public class SQLExceptionCustomTranslatorTests extends TestCase {
33+
34+
private static SQLErrorCodes ERROR_CODES = new SQLErrorCodes();
35+
36+
static {
37+
ERROR_CODES.setBadSqlGrammarCodes(new String[] { "1" });
38+
ERROR_CODES.setDataAccessResourceFailureCodes(new String[] { "2" });
39+
ERROR_CODES.setCustomSqlExceptionTranslatorClass(CustomSqlExceptionTranslator.class);
40+
}
41+
42+
43+
public void testCustomErrorCodeTranslation() {
44+
45+
SQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator(ERROR_CODES);
46+
47+
SQLException dataIntegrityViolationEx = SQLExceptionSubclassFactory.newSQLDataException("", "", 1);
48+
DataAccessException daeex = sext.translate("task", "SQL", dataIntegrityViolationEx);
49+
assertEquals(dataIntegrityViolationEx, daeex.getCause());
50+
assertTrue(daeex instanceof BadSqlGrammarException);
51+
52+
SQLException dataAccessResourceEx = SQLExceptionSubclassFactory.newSQLDataException("", "", 2);
53+
DataAccessException darex = sext.translate("task", "SQL", dataAccessResourceEx);
54+
assertEquals(dataIntegrityViolationEx, daeex.getCause());
55+
assertTrue(darex instanceof TransientDataAccessResourceException);
56+
57+
}
58+
59+
}

0 commit comments

Comments
 (0)