Polishing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -96,7 +96,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
|
||||
* is allowed to return {@code null} to indicate that no exception match has
|
||||
* been found and that fallback translation should kick in.
|
||||
* @param task readable text describing the task being attempted
|
||||
* @param sql SQL query or update that caused the problem (if known)
|
||||
* @param sql the SQL query or update that caused the problem (if known)
|
||||
* @param ex the offending {@code SQLException}
|
||||
* @return the DataAccessException, wrapping the {@code SQLException};
|
||||
* or {@code null} if no exception match found
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -25,12 +25,12 @@ import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link KeyHolder} interface, to be used for
|
||||
* The standard implementation of the {@link KeyHolder} interface, to be used for
|
||||
* holding auto-generated keys (as potentially returned by JDBC insert statements).
|
||||
*
|
||||
* <p>Create an instance of this class for each insert operation, and pass
|
||||
* it to the corresponding {@link org.springframework.jdbc.core.JdbcTemplate}
|
||||
* or {org.springframework.jdbc.object.SqlUpdate} methods.
|
||||
* <p>Create an instance of this class for each insert operation, and pass it
|
||||
* to the corresponding {@link org.springframework.jdbc.core.JdbcTemplate} or
|
||||
* {@link org.springframework.jdbc.object.SqlUpdate} methods.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Juergen Hoeller
|
||||
@@ -59,7 +59,7 @@ public class GeneratedKeyHolder implements KeyHolder {
|
||||
|
||||
@Override
|
||||
public Number getKey() throws InvalidDataAccessApiUsageException, DataRetrievalFailureException {
|
||||
if (this.keyList.size() == 0) {
|
||||
if (this.keyList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (this.keyList.size() > 1 || this.keyList.get(0).size() > 1) {
|
||||
@@ -86,13 +86,14 @@ public class GeneratedKeyHolder implements KeyHolder {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getKeys() throws InvalidDataAccessApiUsageException {
|
||||
if (this.keyList.size() == 0) {
|
||||
if (this.keyList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (this.keyList.size() > 1)
|
||||
if (this.keyList.size() > 1) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"The getKeys method should only be used when keys for a single row are returned. " +
|
||||
"The current key list contains keys for multiple rows: " + this.keyList);
|
||||
}
|
||||
return this.keyList.get(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -51,26 +51,26 @@ public interface KeyHolder {
|
||||
* multiple entries as well. If this method encounters multiple entries in
|
||||
* either the map or the list meaning that multiple keys were returned,
|
||||
* then an InvalidDataAccessApiUsageException is thrown.
|
||||
* @return the generated key
|
||||
* @throws InvalidDataAccessApiUsageException if multiple keys are encountered.
|
||||
* @return the generated key as a number
|
||||
* @throws InvalidDataAccessApiUsageException if multiple keys are encountered
|
||||
*/
|
||||
Number getKey() throws InvalidDataAccessApiUsageException;
|
||||
|
||||
/**
|
||||
* Retrieve the first map of keys. If there are multiple entries in the list
|
||||
* (meaning that multiple rows had keys returned), then an
|
||||
* InvalidDataAccessApiUsageException is thrown.
|
||||
* @return the Map of generated keys
|
||||
* Retrieve the first map of keys.
|
||||
* <p>If there are multiple entries in the list (meaning that multiple rows
|
||||
* had keys returned), then an InvalidDataAccessApiUsageException is thrown.
|
||||
* @return the Map of generated keys for a single row
|
||||
* @throws InvalidDataAccessApiUsageException if keys for multiple rows are encountered
|
||||
*/
|
||||
Map<String, Object> getKeys() throws InvalidDataAccessApiUsageException;
|
||||
|
||||
/**
|
||||
* Return a reference to the List that contains the keys.
|
||||
* Can be used for extracting keys for multiple rows (an unusual case),
|
||||
* <p>Can be used for extracting keys for multiple rows (an unusual case),
|
||||
* and also for adding new maps of keys.
|
||||
* @return the List for the generated keys, with each entry being a Map
|
||||
* of column names and key values
|
||||
* @return the List for the generated keys, with each entry representing
|
||||
* an individual row through a Map of column names and key values
|
||||
*/
|
||||
List<Map<String, Object>> getKeyList();
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
|
||||
* Create a SQL error code translator for the given DataSource.
|
||||
* Invoking this constructor will cause a Connection to be obtained
|
||||
* from the DataSource to get the meta-data.
|
||||
* @param dataSource DataSource to use to find meta-data and establish
|
||||
* @param dataSource the DataSource to use to find meta-data and establish
|
||||
* which error codes are usable
|
||||
* @see SQLErrorCodesFactory
|
||||
*/
|
||||
@@ -125,7 +125,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
|
||||
* Set the DataSource for this translator.
|
||||
* <p>Setting this property will cause a Connection to be obtained from
|
||||
* the DataSource to get the meta-data.
|
||||
* @param dataSource DataSource to use to find meta-data and establish
|
||||
* @param dataSource the DataSource to use to find meta-data and establish
|
||||
* which error codes are usable
|
||||
* @see SQLErrorCodesFactory#getErrorCodes(javax.sql.DataSource)
|
||||
* @see java.sql.DatabaseMetaData#getDatabaseProductName()
|
||||
@@ -176,9 +176,9 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
|
||||
}
|
||||
|
||||
// First, try custom translation from overridden method.
|
||||
DataAccessException dex = customTranslate(task, sql, sqlEx);
|
||||
if (dex != null) {
|
||||
return dex;
|
||||
DataAccessException dae = customTranslate(task, sql, sqlEx);
|
||||
if (dae != null) {
|
||||
return dae;
|
||||
}
|
||||
|
||||
// Next, try the custom SQLException translator, if available.
|
||||
@@ -213,14 +213,13 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
|
||||
CustomSQLErrorCodesTranslation[] customTranslations = this.sqlErrorCodes.getCustomTranslations();
|
||||
if (customTranslations != null) {
|
||||
for (CustomSQLErrorCodesTranslation customTranslation : customTranslations) {
|
||||
if (Arrays.binarySearch(customTranslation.getErrorCodes(), errorCode) >= 0) {
|
||||
if (customTranslation.getExceptionClass() != null) {
|
||||
DataAccessException customException = createCustomException(
|
||||
task, sql, sqlEx, customTranslation.getExceptionClass());
|
||||
if (customException != null) {
|
||||
logTranslation(task, sql, sqlEx, true);
|
||||
return customException;
|
||||
}
|
||||
if (Arrays.binarySearch(customTranslation.getErrorCodes(), errorCode) >= 0 &&
|
||||
customTranslation.getExceptionClass() != null) {
|
||||
DataAccessException customException = createCustomException(
|
||||
task, sql, sqlEx, customTranslation.getExceptionClass());
|
||||
if (customException != null) {
|
||||
logTranslation(task, sql, sqlEx, true);
|
||||
return customException;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,65 +284,65 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can override this method to attempt a custom mapping from SQLException
|
||||
* to DataAccessException.
|
||||
* Subclasses can override this method to attempt a custom mapping from
|
||||
* {@link SQLException} to {@link DataAccessException}.
|
||||
* @param task readable text describing the task being attempted
|
||||
* @param sql SQL query or update that caused the problem. May be {@code null}.
|
||||
* @param sql the SQL query or update that caused the problem (may be {@code null})
|
||||
* @param sqlEx the offending SQLException
|
||||
* @return null if no custom translation was possible, otherwise a DataAccessException
|
||||
* resulting from custom translation. This exception should include the sqlEx parameter
|
||||
* as a nested root cause. This implementation always returns null, meaning that
|
||||
* the translator always falls back to the default error codes.
|
||||
* @return {@code null} if no custom translation applies, otherwise a {@link DataAccessException}
|
||||
* resulting from custom translation. This exception should include the {@code sqlEx} parameter
|
||||
* as a nested root cause. This implementation always returns {@code null}, meaning that the
|
||||
* translator always falls back to the default error codes.
|
||||
*/
|
||||
protected DataAccessException customTranslate(String task, String sql, SQLException sqlEx) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a custom DataAccessException, based on a given exception
|
||||
* class from a CustomSQLErrorCodesTranslation definition.
|
||||
* Create a custom {@link DataAccessException}, based on a given exception
|
||||
* class from a {@link CustomSQLErrorCodesTranslation} definition.
|
||||
* @param task readable text describing the task being attempted
|
||||
* @param sql SQL query or update that caused the problem. May be {@code null}.
|
||||
* @param sql the SQL query or update that caused the problem (may be {@code null})
|
||||
* @param sqlEx the offending SQLException
|
||||
* @param exceptionClass the exception class to use, as defined in the
|
||||
* CustomSQLErrorCodesTranslation definition
|
||||
* @return null if the custom exception could not be created, otherwise
|
||||
* the resulting DataAccessException. This exception should include the
|
||||
* sqlEx parameter as a nested root cause.
|
||||
* {@link CustomSQLErrorCodesTranslation} definition
|
||||
* @return {@code null} if the custom exception could not be created, otherwise
|
||||
* the resulting {@link DataAccessException}. This exception should include the
|
||||
* {@code sqlEx} parameter as a nested root cause.
|
||||
* @see CustomSQLErrorCodesTranslation#setExceptionClass
|
||||
*/
|
||||
protected DataAccessException createCustomException(
|
||||
String task, String sql, SQLException sqlEx, Class<?> exceptionClass) {
|
||||
|
||||
// find appropriate constructor
|
||||
// Find appropriate constructor for the given exception class
|
||||
try {
|
||||
int constructorType = 0;
|
||||
Constructor<?>[] constructors = exceptionClass.getConstructors();
|
||||
for (Constructor<?> constructor : constructors) {
|
||||
Class<?>[] parameterTypes = constructor.getParameterTypes();
|
||||
if (parameterTypes.length == 1 && String.class == parameterTypes[0]) {
|
||||
if (constructorType < MESSAGE_ONLY_CONSTRUCTOR)
|
||||
constructorType = MESSAGE_ONLY_CONSTRUCTOR;
|
||||
if (parameterTypes.length == 1 && String.class == parameterTypes[0] &&
|
||||
constructorType < MESSAGE_ONLY_CONSTRUCTOR) {
|
||||
constructorType = MESSAGE_ONLY_CONSTRUCTOR;
|
||||
}
|
||||
if (parameterTypes.length == 2 && String.class == parameterTypes[0] &&
|
||||
Throwable.class == parameterTypes[1]) {
|
||||
if (constructorType < MESSAGE_THROWABLE_CONSTRUCTOR)
|
||||
constructorType = MESSAGE_THROWABLE_CONSTRUCTOR;
|
||||
Throwable.class == parameterTypes[1] &&
|
||||
constructorType < MESSAGE_THROWABLE_CONSTRUCTOR) {
|
||||
constructorType = MESSAGE_THROWABLE_CONSTRUCTOR;
|
||||
}
|
||||
if (parameterTypes.length == 2 && String.class == parameterTypes[0] &&
|
||||
SQLException.class == parameterTypes[1]) {
|
||||
if (constructorType < MESSAGE_SQLEX_CONSTRUCTOR)
|
||||
constructorType = MESSAGE_SQLEX_CONSTRUCTOR;
|
||||
SQLException.class == parameterTypes[1] &&
|
||||
constructorType < MESSAGE_SQLEX_CONSTRUCTOR) {
|
||||
constructorType = MESSAGE_SQLEX_CONSTRUCTOR;
|
||||
}
|
||||
if (parameterTypes.length == 3 && String.class == parameterTypes[0] &&
|
||||
String.class == parameterTypes[1] && Throwable.class == parameterTypes[2]) {
|
||||
if (constructorType < MESSAGE_SQL_THROWABLE_CONSTRUCTOR)
|
||||
constructorType = MESSAGE_SQL_THROWABLE_CONSTRUCTOR;
|
||||
String.class == parameterTypes[1] && Throwable.class == parameterTypes[2] &&
|
||||
constructorType < MESSAGE_SQL_THROWABLE_CONSTRUCTOR) {
|
||||
constructorType = MESSAGE_SQL_THROWABLE_CONSTRUCTOR;
|
||||
}
|
||||
if (parameterTypes.length == 3 && String.class == parameterTypes[0] &&
|
||||
String.class == parameterTypes[1] && SQLException.class == parameterTypes[2]) {
|
||||
if (constructorType < MESSAGE_SQL_SQLEX_CONSTRUCTOR)
|
||||
constructorType = MESSAGE_SQL_SQLEX_CONSTRUCTOR;
|
||||
String.class == parameterTypes[1] && SQLException.class == parameterTypes[2] &&
|
||||
constructorType < MESSAGE_SQL_SQLEX_CONSTRUCTOR) {
|
||||
constructorType = MESSAGE_SQL_SQLEX_CONSTRUCTOR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -44,9 +44,12 @@ public interface SQLExceptionTranslator {
|
||||
* check (and subsequent cast) is considered reliable when expecting JDBC-based
|
||||
* access to have happened.
|
||||
* @param task readable text describing the task being attempted
|
||||
* @param sql SQL query or update that caused the problem (may be {@code null})
|
||||
* @param sql the SQL query or update that caused the problem (if known)
|
||||
* @param ex the offending {@code SQLException}
|
||||
* @return the DataAccessException, wrapping the {@code SQLException}
|
||||
* @return the DataAccessException wrapping the {@code SQLException},
|
||||
* or {@code null} if no translation could be applied
|
||||
* (in a custom translator; the default translators always throw an
|
||||
* {@link org.springframework.jdbc.UncategorizedSQLException} in such a case)
|
||||
* @see org.springframework.dao.DataAccessException#getRootCause()
|
||||
*/
|
||||
DataAccessException translate(String task, String sql, SQLException ex);
|
||||
|
||||
Reference in New Issue
Block a user