SQLErrorCodeSQLExceptionTranslator tries to find SQLException with actual error code, looping through the causes.

Issue: SPR-10260
master
Juergen Hoeller 12 years ago
parent 188a11bdb9
commit 8a4ce142c4
  1. 26
      spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java
  2. 20
      spring-jdbc/src/test/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslatorTests.java

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,7 +20,6 @@ import java.lang.reflect.Constructor;
import java.sql.BatchUpdateException;
import java.sql.SQLException;
import java.util.Arrays;
import javax.sql.DataSource;
import org.springframework.core.JdkVersion;
@ -30,9 +29,9 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DeadlockLoserDataAccessException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.PermissionDeniedDataAccessException;
import org.springframework.dao.TransientDataAccessResourceException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.InvalidResultSetAccessException;
@ -201,20 +200,25 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
// Check SQLErrorCodes with corresponding error code, if available.
if (this.sqlErrorCodes != null) {
String errorCode = null;
String errorCode;
if (this.sqlErrorCodes.isUseSqlStateForTranslation()) {
errorCode = sqlEx.getSQLState();
}
else {
errorCode = Integer.toString(sqlEx.getErrorCode());
// Try to find SQLException with actual error code, looping through the causes.
// E.g. applicable to java.sql.DataTruncation as of JDK 1.6.
SQLException current = sqlEx;
while (current.getErrorCode() == 0 && current.getCause() instanceof SQLException) {
current = (SQLException) current.getCause();
}
errorCode = Integer.toString(current.getErrorCode());
}
if (errorCode != null) {
// Look for defined custom translations first.
CustomSQLErrorCodesTranslation[] customTranslations = this.sqlErrorCodes.getCustomTranslations();
if (customTranslations != null) {
for (int i = 0; i < customTranslations.length; i++) {
CustomSQLErrorCodesTranslation customTranslation = customTranslations[i];
for (CustomSQLErrorCodesTranslation customTranslation : customTranslations) {
if (Arrays.binarySearch(customTranslation.getErrorCodes(), errorCode) >= 0) {
if (customTranslation.getExceptionClass() != null) {
DataAccessException customException = createCustomException(
@ -273,7 +277,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
// We couldn't identify it more precisely - let's hand it over to the SQLState fallback translator.
if (logger.isDebugEnabled()) {
String codes = null;
String codes;
if (this.sqlErrorCodes != null && this.sqlErrorCodes.isUseSqlStateForTranslation()) {
codes = "SQL state '" + sqlEx.getSQLState() + "', error code '" + sqlEx.getErrorCode();
}
@ -321,8 +325,8 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
try {
int constructorType = 0;
Constructor[] constructors = exceptionClass.getConstructors();
for (int i = 0; i < constructors.length; i++) {
Class[] parameterTypes = constructors[i].getParameterTypes();
for (Constructor constructor : constructors) {
Class[] parameterTypes = constructor.getParameterTypes();
if (parameterTypes.length == 1 && parameterTypes[0].equals(String.class)) {
if (constructorType < MESSAGE_ONLY_CONSTRUCTOR)
constructorType = MESSAGE_ONLY_CONSTRUCTOR;
@ -350,7 +354,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
}
// invoke constructor
Constructor exceptionConstructor = null;
Constructor exceptionConstructor;
switch (constructorType) {
case MESSAGE_SQL_SQLEX_CONSTRUCTOR:
Class[] messageAndSqlAndSqlExArgsClass = new Class[] {String.class, String.class, SQLException.class};

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +16,9 @@
package org.springframework.jdbc.support;
import java.sql.SQLException;
import java.sql.BatchUpdateException;
import java.sql.DataTruncation;
import java.sql.SQLException;
import junit.framework.TestCase;
@ -33,6 +34,7 @@ import org.springframework.jdbc.InvalidResultSetAccessException;
/**
* @author Rod Johnson
* @author Juergen Hoeller
*/
public class SQLErrorCodeSQLExceptionTranslatorTests extends TestCase {
@ -92,13 +94,21 @@ public class SQLErrorCodeSQLExceptionTranslatorTests extends TestCase {
SQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator(ERROR_CODES);
SQLException badSqlEx = new SQLException("", "", 1);
BatchUpdateException batchUdateEx = new BatchUpdateException();
batchUdateEx.setNextException(badSqlEx);
BadSqlGrammarException bsgex = (BadSqlGrammarException) sext.translate("task", "SQL", batchUdateEx);
BatchUpdateException batchUpdateEx = new BatchUpdateException();
batchUpdateEx.setNextException(badSqlEx);
BadSqlGrammarException bsgex = (BadSqlGrammarException) sext.translate("task", "SQL", batchUpdateEx);
assertEquals("SQL", bsgex.getSql());
assertEquals(badSqlEx, bsgex.getSQLException());
}
public void testDataTruncationTranslation() {
SQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator(ERROR_CODES);
SQLException dataAccessEx = new SQLException("", "", 5);
DataTruncation dataTruncation = new DataTruncation(1, true, true, 1, 1, dataAccessEx);
DataAccessResourceFailureException daex = (DataAccessResourceFailureException) sext.translate("task", "SQL", dataTruncation);
assertEquals(dataTruncation, daex.getCause());
}
@SuppressWarnings("serial")
public void testCustomTranslateMethodTranslation() {

Loading…
Cancel
Save