From e94624d4398f064f54bc9bcd3b82cbc217ff5e22 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 18 Sep 2018 22:09:07 +0200 Subject: [PATCH] Polishing --- ...bstractFallbackSQLExceptionTranslator.java | 4 +- .../jdbc/support/GeneratedKeyHolder.java | 17 ++-- .../jdbc/support/KeyHolder.java | 20 ++--- .../SQLErrorCodeSQLExceptionTranslator.java | 85 +++++++++---------- .../jdbc/support/SQLExceptionTranslator.java | 9 +- 5 files changed, 69 insertions(+), 66 deletions(-) diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java index 2e46da56d3b..dee2182b29c 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java @@ -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 diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/GeneratedKeyHolder.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/GeneratedKeyHolder.java index abdab1e872f..a897355de8b 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/GeneratedKeyHolder.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/GeneratedKeyHolder.java @@ -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). * - *

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. + *

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 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); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/KeyHolder.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/KeyHolder.java index b917ecb95d3..6b4cfaf4d0f 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/KeyHolder.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/KeyHolder.java @@ -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. + *

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 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), + *

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> getKeyList(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java index a71156badb1..fe6445ed33e 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java @@ -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. *

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; } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionTranslator.java index 87a84c8dc15..634159a7458 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionTranslator.java @@ -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);