Introduce null-safety of Spring Framework API

This commit introduces 2 new @Nullable and @NonNullApi
annotations that leverage JSR 305 (dormant but available via
Findbugs jsr305 dependency and already used by libraries
like OkHttp) meta-annotations to specify explicitly
null-safety of Spring Framework parameters and return values.

In order to avoid adding too much annotations, the
default is set at package level with @NonNullApi and
@Nullable annotations are added when needed at parameter or
return value level. These annotations are intended to be used
on Spring Framework itself but also by other Spring projects.

@Nullable annotations have been introduced based on Javadoc
and search of patterns like "return null;". It is expected that
nullability of Spring Framework API will be polished with
complementary commits.

In practice, this will make the whole Spring Framework API
null-safe for Kotlin projects (when KT-10942 will be fixed)
since Kotlin will be able to leverage these annotations to
know if a parameter or a return value is nullable or not. But
this is also useful for Java developers as well since IntelliJ
IDEA, for example, also understands these annotations to
generate warnings when unsafe nullable usages are detected.

Issue: SPR-15540
This commit is contained in:
Sebastien Deleuze
2017-05-27 08:14:59 +02:00
parent 2d37c966b2
commit 87598f48e4
1315 changed files with 4831 additions and 963 deletions

View File

@@ -27,6 +27,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.jdbc.datasource.init.CompositeDatabasePopulator;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
@@ -82,6 +83,7 @@ class DatabasePopulatorConfigUtils {
return builder.getBeanDefinition();
}
@Nullable
private static String getSeparator(Element element, Element scriptElement) {
String scriptSeparator = scriptElement.getAttribute("separator");
if (StringUtils.hasLength(scriptSeparator)) {

View File

@@ -1,4 +1,7 @@
/**
* Defines the Spring JDBC configuration namespace.
*/
@NonNullApi
package org.springframework.jdbc.config;
import org.springframework.lang.NonNullApi;

View File

@@ -39,6 +39,7 @@ import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -192,7 +193,7 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> {
* @since 4.3
* @see #initBeanWrapper(BeanWrapper)
*/
public void setConversionService(ConversionService conversionService) {
public void setConversionService(@Nullable ConversionService conversionService) {
this.conversionService = conversionService;
}
@@ -201,6 +202,7 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> {
* or {@code null} if none.
* @since 4.3
*/
@Nullable
public ConversionService getConversionService() {
return this.conversionService;
}
@@ -366,7 +368,7 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> {
* @throws SQLException in case of extraction failure
* @see org.springframework.jdbc.support.JdbcUtils#getResultSetValue(java.sql.ResultSet, int, Class)
*/
protected Object getColumnValue(ResultSet rs, int index, PropertyDescriptor pd) throws SQLException {
protected Object getColumnValue(ResultSet rs, int index, @Nullable PropertyDescriptor pd) throws SQLException {
return JdbcUtils.getResultSetValue(rs, index, pd.getPropertyType());
}

View File

@@ -20,6 +20,7 @@ import java.sql.CallableStatement;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Generic callback interface for code that operates on a CallableStatement.
@@ -73,6 +74,7 @@ public interface CallableStatementCallback<T> {
* into a DataAccessException by a SQLExceptionTranslator
* @throws DataAccessException in case of custom exceptions
*/
@Nullable
T doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException;
}

View File

@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Map;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.lang.Nullable;
/**
* Helper class that efficiently creates multiple {@link CallableStatementCreator}
@@ -102,7 +103,7 @@ public class CallableStatementCreatorFactory {
* Return a new CallableStatementCreator instance given this parameters.
* @param params list of parameters (may be {@code null})
*/
public CallableStatementCreator newCallableStatementCreator(Map<String, ?> params) {
public CallableStatementCreator newCallableStatementCreator(@Nullable Map<String, ?> params) {
return new CallableStatementCreatorImpl(params != null ? params : new HashMap<>());
}

View File

@@ -20,6 +20,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Generic callback interface for code that operates on a JDBC Connection.
@@ -62,6 +63,7 @@ public interface ConnectionCallback<T> {
* @see JdbcTemplate#queryForObject(String, Class)
* @see JdbcTemplate#queryForRowSet(String)
*/
@Nullable
T doInConnection(Connection con) throws SQLException, DataAccessException;
}

View File

@@ -24,6 +24,7 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.lang.Nullable;
/**
* Interface specifying a basic set of JDBC operations.
@@ -59,6 +60,7 @@ public interface JdbcOperations {
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(ConnectionCallback<T> action) throws DataAccessException;
@@ -78,6 +80,7 @@ public interface JdbcOperations {
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(StatementCallback<T> action) throws DataAccessException;
/**
@@ -162,6 +165,7 @@ public interface JdbcOperations {
* @throws DataAccessException if there is any problem executing the query
* @see #queryForObject(String, Object[], Class)
*/
@Nullable
<T> T queryForObject(String sql, Class<T> requiredType) throws DataAccessException;
/**
@@ -288,6 +292,7 @@ public interface JdbcOperations {
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException;
/**
@@ -315,7 +320,7 @@ public interface JdbcOperations {
* @return an arbitrary result object, as returned by the ResultSetExtractor
* @throws DataAccessException if there is any problem
*/
<T> T query(String sql, PreparedStatementSetter pss, ResultSetExtractor<T> rse) throws DataAccessException;
<T> T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor<T> rse) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a list
@@ -360,7 +365,7 @@ public interface JdbcOperations {
* @return an arbitrary result object, as returned by the ResultSetExtractor
* @throws DataAccessException if the query fails
*/
<T> T query(String sql, ResultSetExtractor<T> rse, Object... args) throws DataAccessException;
<T> T query(String sql, ResultSetExtractor<T> rse, @Nullable Object... args) throws DataAccessException;
/**
* Query using a prepared statement, reading the ResultSet on a per-row
@@ -387,7 +392,7 @@ public interface JdbcOperations {
* @param rch object that will extract results, one row at a time
* @throws DataAccessException if the query fails
*/
void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch) throws DataAccessException;
void query(String sql, @Nullable PreparedStatementSetter pss, RowCallbackHandler rch) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a list of
@@ -429,7 +434,7 @@ public interface JdbcOperations {
* only the argument value but also the SQL type and optionally the scale
* @throws DataAccessException if the query fails
*/
void query(String sql, RowCallbackHandler rch, Object... args) throws DataAccessException;
void query(String sql, RowCallbackHandler rch, @Nullable Object... args) throws DataAccessException;
/**
* Query using a prepared statement, mapping each row to a Java object
@@ -457,7 +462,7 @@ public interface JdbcOperations {
* @return the result List, containing mapped objects
* @throws DataAccessException if the query fails
*/
<T> List<T> query(String sql, PreparedStatementSetter pss, RowMapper<T> rowMapper) throws DataAccessException;
<T> List<T> query(String sql, @Nullable PreparedStatementSetter pss, RowMapper<T> rowMapper) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a list
@@ -502,7 +507,7 @@ public interface JdbcOperations {
* @return the result List, containing mapped objects
* @throws DataAccessException if the query fails
*/
<T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException;
<T> List<T> query(String sql, RowMapper<T> rowMapper, @Nullable Object... args) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a list
@@ -554,7 +559,7 @@ public interface JdbcOperations {
* return exactly one row
* @throws DataAccessException if the query fails
*/
<T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException;
<T> T queryForObject(String sql, RowMapper<T> rowMapper, @Nullable Object... args) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a
@@ -573,6 +578,7 @@ public interface JdbcOperations {
* @see #queryForObject(String, Class)
* @see java.sql.Types
*/
@Nullable
<T> T queryForObject(String sql, Object[] args, int[] argTypes, Class<T> requiredType)
throws DataAccessException;
@@ -593,6 +599,7 @@ public interface JdbcOperations {
* @throws DataAccessException if the query fails
* @see #queryForObject(String, Class)
*/
@Nullable
<T> T queryForObject(String sql, Object[] args, Class<T> requiredType) throws DataAccessException;
/**
@@ -612,7 +619,8 @@ public interface JdbcOperations {
* @throws DataAccessException if the query fails
* @see #queryForObject(String, Class)
*/
<T> T queryForObject(String sql, Class<T> requiredType, Object... args) throws DataAccessException;
@Nullable
<T> T queryForObject(String sql, Class<T> requiredType, @Nullable Object... args) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a
@@ -655,7 +663,7 @@ public interface JdbcOperations {
* @see #queryForMap(String)
* @see ColumnMapRowMapper
*/
Map<String, Object> queryForMap(String sql, Object... args) throws DataAccessException;
Map<String, Object> queryForMap(String sql, @Nullable Object... args) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a
@@ -712,7 +720,7 @@ public interface JdbcOperations {
* @see #queryForList(String, Class)
* @see SingleColumnRowMapper
*/
<T> List<T> queryForList(String sql, Class<T> elementType, Object... args) throws DataAccessException;
<T> List<T> queryForList(String sql, Class<T> elementType, @Nullable Object... args) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a
@@ -748,7 +756,7 @@ public interface JdbcOperations {
* @throws DataAccessException if the query fails
* @see #queryForList(String)
*/
List<Map<String, Object>> queryForList(String sql, Object... args) throws DataAccessException;
List<Map<String, Object>> queryForList(String sql, @Nullable Object... args) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a
@@ -794,7 +802,7 @@ public interface JdbcOperations {
* @see SqlRowSetResultSetExtractor
* @see javax.sql.rowset.CachedRowSet
*/
SqlRowSet queryForRowSet(String sql, Object... args) throws DataAccessException;
SqlRowSet queryForRowSet(String sql, @Nullable Object... args) throws DataAccessException;
/**
* Issue a single SQL update operation (such as an insert, update or delete statement)
@@ -834,7 +842,7 @@ public interface JdbcOperations {
* @return the number of rows affected
* @throws DataAccessException if there is any problem issuing the update
*/
int update(String sql, PreparedStatementSetter pss) throws DataAccessException;
int update(String sql, @Nullable PreparedStatementSetter pss) throws DataAccessException;
/**
* Issue a single SQL update operation (such as an insert, update or delete statement)
@@ -860,7 +868,7 @@ public interface JdbcOperations {
* @return the number of rows affected
* @throws DataAccessException if there is any problem issuing the update
*/
int update(String sql, Object... args) throws DataAccessException;
int update(String sql, @Nullable Object... args) throws DataAccessException;
/**
* Issue multiple update statements on a single PreparedStatement,
@@ -926,6 +934,7 @@ public interface JdbcOperations {
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action) throws DataAccessException;
/**
@@ -941,6 +950,7 @@ public interface JdbcOperations {
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(String callString, CallableStatementCallback<T> action) throws DataAccessException;
/**

View File

@@ -35,6 +35,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
@@ -47,6 +48,7 @@ import org.springframework.jdbc.support.JdbcAccessor;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.util.StringUtils;
@@ -1349,7 +1351,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
* May be {@code null}, in which case this method does nothing.
* @throws SQLWarningException in case of an actual warning to be raised
*/
protected void handleWarnings(SQLWarning warning) throws SQLWarningException {
protected void handleWarnings(@Nullable SQLWarning warning) throws SQLWarningException {
if (warning != null) {
throw new SQLWarningException("Warning not ignored", warning);
}
@@ -1361,6 +1363,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
* @return the SQL string, or {@code null}
* @see SqlProvider
*/
@Nullable
private static String getSql(Object sqlProvider) {
if (sqlProvider instanceof SqlProvider) {
return ((SqlProvider) sqlProvider).getSql();
@@ -1385,6 +1388,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on ConnectionProxy interface coming in...

View File

@@ -20,6 +20,8 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import org.springframework.lang.Nullable;
/**
* Implement this interface when parameters need to be customized based
* on the connection. We might need to do this to make use of proprietary
@@ -43,6 +45,7 @@ public interface ParameterMapper {
* parameter values (that is, there's no need to catch SQLException)
* @return Map of input parameters, keyed by name (never {@code null})
*/
@Nullable
Map<String, ?> createMap(Connection con) throws SQLException;
}

View File

@@ -20,6 +20,7 @@ import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Generic callback interface for code that operates on a PreparedStatement.
@@ -72,6 +73,7 @@ public interface PreparedStatementCallback<T> {
* @see JdbcTemplate#queryForObject(String, Object[], Class)
* @see JdbcTemplate#queryForList(String, Object[])
*/
@Nullable
T doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException;
}

View File

@@ -30,6 +30,7 @@ import java.util.List;
import java.util.Set;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -135,7 +136,7 @@ public class PreparedStatementCreatorFactory {
* Return a new PreparedStatementSetter for the given parameters.
* @param params list of parameters (may be {@code null})
*/
public PreparedStatementSetter newPreparedStatementSetter(List<?> params) {
public PreparedStatementSetter newPreparedStatementSetter(@Nullable List<?> params) {
return new PreparedStatementCreatorImpl(params != null ? params : Collections.emptyList());
}
@@ -143,7 +144,7 @@ public class PreparedStatementCreatorFactory {
* Return a new PreparedStatementSetter for the given parameters.
* @param params the parameter array (may be {@code null})
*/
public PreparedStatementSetter newPreparedStatementSetter(Object[] params) {
public PreparedStatementSetter newPreparedStatementSetter(@Nullable Object[] params) {
return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.emptyList());
}
@@ -151,7 +152,7 @@ public class PreparedStatementCreatorFactory {
* Return a new PreparedStatementCreator for the given parameters.
* @param params list of parameters (may be {@code null})
*/
public PreparedStatementCreator newPreparedStatementCreator(List<?> params) {
public PreparedStatementCreator newPreparedStatementCreator(@Nullable List<?> params) {
return new PreparedStatementCreatorImpl(params != null ? params : Collections.emptyList());
}
@@ -159,7 +160,7 @@ public class PreparedStatementCreatorFactory {
* Return a new PreparedStatementCreator for the given parameters.
* @param params the parameter array (may be {@code null})
*/
public PreparedStatementCreator newPreparedStatementCreator(Object[] params) {
public PreparedStatementCreator newPreparedStatementCreator(@Nullable Object[] params) {
return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.emptyList());
}
@@ -169,7 +170,7 @@ public class PreparedStatementCreatorFactory {
* the factory's, for example because of named parameter expanding)
* @param params the parameter array (may be {@code null})
*/
public PreparedStatementCreator newPreparedStatementCreator(String sqlToUse, Object[] params) {
public PreparedStatementCreator newPreparedStatementCreator(String sqlToUse, @Nullable Object[] params) {
return new PreparedStatementCreatorImpl(
sqlToUse, params != null ? Arrays.asList(params) : Collections.emptyList());
}

View File

@@ -20,6 +20,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Callback interface used by {@link JdbcTemplate}'s query methods.
@@ -59,6 +60,7 @@ public interface ResultSetExtractor<T> {
* values or navigating (that is, there's no need to catch SQLException)
* @throws DataAccessException in case of custom exceptions
*/
@Nullable
T extractData(ResultSet rs) throws SQLException, DataAccessException;
}

View File

@@ -16,6 +16,8 @@
package org.springframework.jdbc.core;
import org.springframework.lang.Nullable;
/**
* Common base class for ResultSet-supporting SqlParameters like
* {@link SqlOutParameter} and {@link SqlReturnResultSet}.
@@ -107,6 +109,7 @@ public class ResultSetSupportingSqlParameter extends SqlParameter {
/**
* Return the ResultSetExtractor held by this parameter, if any.
*/
@Nullable
public ResultSetExtractor<?> getResultSetExtractor() {
return this.resultSetExtractor;
}
@@ -114,6 +117,7 @@ public class ResultSetSupportingSqlParameter extends SqlParameter {
/**
* Return the RowCallbackHandler held by this parameter, if any.
*/
@Nullable
public RowCallbackHandler getRowCallbackHandler() {
return this.rowCallbackHandler;
}
@@ -121,6 +125,7 @@ public class ResultSetSupportingSqlParameter extends SqlParameter {
/**
* Return the RowMapper held by this parameter, if any.
*/
@Nullable
public RowMapper<?> getRowMapper() {
return this.rowMapper;
}

View File

@@ -23,6 +23,7 @@ import java.sql.SQLException;
import org.springframework.dao.TypeMismatchDataAccessException;
import org.springframework.jdbc.IncorrectResultSetColumnCountException;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.NumberUtils;
@@ -125,7 +126,7 @@ public class SingleColumnRowMapper<T> implements RowMapper<T> {
* @see org.springframework.jdbc.support.JdbcUtils#getResultSetValue(java.sql.ResultSet, int, Class)
* @see #getColumnValue(java.sql.ResultSet, int)
*/
protected Object getColumnValue(ResultSet rs, int index, Class<?> requiredType) throws SQLException {
protected Object getColumnValue(ResultSet rs, int index, @Nullable Class<?> requiredType) throws SQLException {
if (requiredType != null) {
return JdbcUtils.getResultSetValue(rs, index, requiredType);
}

View File

@@ -16,6 +16,8 @@
package org.springframework.jdbc.core;
import org.springframework.lang.Nullable;
/**
* Subclass of SqlParameter to represent an output parameter.
* No additional properties: instanceof will be used to check
@@ -111,6 +113,7 @@ public class SqlOutParameter extends ResultSetSupportingSqlParameter {
/**
* Return the custom return type, if any.
*/
@Nullable
public SqlReturnType getSqlReturnType() {
return this.sqlReturnType;
}

View File

@@ -19,6 +19,7 @@ package org.springframework.jdbc.core;
import java.util.LinkedList;
import java.util.List;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -127,6 +128,7 @@ public class SqlParameter {
/**
* Return the name of the parameter, or {@code null} if anonymous.
*/
@Nullable
public String getName() {
return this.name;
}
@@ -141,6 +143,7 @@ public class SqlParameter {
/**
* Return the type name of the parameter, if any.
*/
@Nullable
public String getTypeName() {
return this.typeName;
}
@@ -148,6 +151,7 @@ public class SqlParameter {
/**
* Return the scale of the parameter, if any.
*/
@Nullable
public Integer getScale() {
return this.scale;
}

View File

@@ -16,6 +16,8 @@
package org.springframework.jdbc.core;
import org.springframework.lang.Nullable;
/**
* Interface to be implemented by objects that can provide SQL strings.
*
@@ -36,6 +38,7 @@ public interface SqlProvider {
* typically the SQL used for creating statements.
* @return the SQL string, or {@code null}
*/
@Nullable
String getSql();
}

View File

@@ -20,6 +20,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Generic callback interface for code that operates on a JDBC Statement.
@@ -65,6 +66,7 @@ public interface StatementCallback<T> {
* @see JdbcTemplate#queryForObject(String, Class)
* @see JdbcTemplate#queryForRowSet(String)
*/
@Nullable
T doInStatement(Statement stmt) throws SQLException, DataAccessException;
}

View File

@@ -37,6 +37,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.SpringProperties;
import org.springframework.jdbc.support.SqlValue;
import org.springframework.lang.Nullable;
/**
* Utility methods for PreparedStatementSetter/Creator and CallableStatementCreator
@@ -111,6 +112,7 @@ public abstract class StatementCreatorUtils {
* @param javaType the Java type to translate
* @return the corresponding SQL type, or {@code null} if none found
*/
@Nullable
public static int javaTypeToSqlParameterType(Class<?> javaType) {
Integer sqlType = javaTypeToSqlTypeMap.get(javaType);
if (sqlType != null) {
@@ -422,7 +424,7 @@ public abstract class StatementCreatorUtils {
* @see DisposableSqlTypeValue#cleanup()
* @see org.springframework.jdbc.core.support.SqlLobValue#cleanup()
*/
public static void cleanupParameters(Object... paramValues) {
public static void cleanupParameters(@Nullable Object... paramValues) {
if (paramValues != null) {
cleanupParameters(Arrays.asList(paramValues));
}
@@ -435,7 +437,7 @@ public abstract class StatementCreatorUtils {
* @see DisposableSqlTypeValue#cleanup()
* @see org.springframework.jdbc.core.support.SqlLobValue#cleanup()
*/
public static void cleanupParameters(Collection<?> paramValues) {
public static void cleanupParameters(@Nullable Collection<?> paramValues) {
if (paramValues != null) {
for (Object inValue : paramValues) {
if (inValue instanceof DisposableSqlTypeValue) {

View File

@@ -21,6 +21,7 @@ import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.lang.Nullable;
/**
* Interface specifying the API to be implemented by a class providing call metadata.
@@ -52,25 +53,28 @@ public interface CallMetaDataProvider {
* @see org.springframework.jdbc.core.simple.SimpleJdbcCall#withoutProcedureColumnMetaDataAccess()
*/
void initializeWithProcedureColumnMetaData(
DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String procedureName)
DatabaseMetaData databaseMetaData, @Nullable String catalogName, @Nullable String schemaName, String procedureName)
throws SQLException;
/**
* Provide any modification of the procedure name passed in to match the meta data currently used.
* This could include altering the case.
*/
@Nullable
String procedureNameToUse(String procedureName);
/**
* Provide any modification of the catalog name passed in to match the meta data currently used.
* This could include altering the case.
*/
@Nullable
String catalogNameToUse(String catalogName);
/**
* Provide any modification of the schema name passed in to match the meta data currently used.
* This could include altering the case.
*/
@Nullable
String schemaNameToUse(String schemaName);
/**
@@ -78,6 +82,7 @@ public interface CallMetaDataProvider {
* The returned value will be used for meta data lookups. This could include altering the case
* used or providing a base catalog if none is provided.
*/
@Nullable
String metaDataCatalogNameToUse(String catalogName) ;
/**
@@ -85,6 +90,7 @@ public interface CallMetaDataProvider {
* The returned value will be used for meta data lookups. This could include altering the case
* used or providing a base schema if none is provided.
*/
@Nullable
String metaDataSchemaNameToUse(String schemaName) ;
/**

View File

@@ -20,6 +20,8 @@ import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.List;
import org.springframework.lang.Nullable;
/**
* Interface specifying the API to be implemented by a class providing table metadata.
* This is intended for internal use by the Simple JDBC classes.
@@ -46,7 +48,7 @@ public interface TableMetaDataProvider {
* @throws SQLException in case of initialization failure
*/
void initializeWithTableColumnMetaData(
DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String tableName)
DatabaseMetaData databaseMetaData, @Nullable String catalogName, @Nullable String schemaName, String tableName)
throws SQLException;
/**
@@ -99,6 +101,7 @@ public interface TableMetaDataProvider {
/**
* Get the simple query to retrieve a generated key
*/
@Nullable
String getSimpleQueryForGetGeneratedKey(String tableName, String keyColumnName);
/**

View File

@@ -1,4 +1,7 @@
/**
* Context metadata abstraction for the configuration and execution of a stored procedure call.
*/
@NonNullApi
package org.springframework.jdbc.core.metadata;
import org.springframework.lang.NonNullApi;

View File

@@ -21,6 +21,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -69,7 +70,7 @@ public class MapSqlParameterSource extends AbstractSqlParameterSource {
* Create a new MapSqlParameterSource based on a Map.
* @param values a Map holding existing parameter values (can be {@code null})
*/
public MapSqlParameterSource(Map<String, ?> values) {
public MapSqlParameterSource(@Nullable Map<String, ?> values) {
addValues(values);
}
@@ -128,7 +129,7 @@ public class MapSqlParameterSource extends AbstractSqlParameterSource {
* @return a reference to this parameter source,
* so it's possible to chain several calls together
*/
public MapSqlParameterSource addValues(Map<String, ?> values) {
public MapSqlParameterSource addValues(@Nullable Map<String, ?> values) {
if (values != null) {
for (Map.Entry<String, ?> entry : values.entrySet()) {
this.values.put(entry.getKey(), entry.getValue());

View File

@@ -27,6 +27,7 @@ import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.lang.Nullable;
/**
* Interface specifying a basic set of JDBC operations allowing the use
@@ -67,6 +68,7 @@ public interface NamedParameterJdbcOperations {
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(String sql, SqlParameterSource paramSource, PreparedStatementCallback<T> action)
throws DataAccessException;
@@ -85,6 +87,7 @@ public interface NamedParameterJdbcOperations {
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(String sql, Map<String, ?> paramMap, PreparedStatementCallback<T> action)
throws DataAccessException;
@@ -101,6 +104,7 @@ public interface NamedParameterJdbcOperations {
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException;
/**
@@ -267,6 +271,7 @@ public interface NamedParameterJdbcOperations {
* @throws org.springframework.dao.DataAccessException if the query fails
* @see org.springframework.jdbc.core.JdbcTemplate#queryForObject(String, Class)
*/
@Nullable
<T> T queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType)
throws DataAccessException;
@@ -286,6 +291,7 @@ public interface NamedParameterJdbcOperations {
* @throws org.springframework.dao.DataAccessException if the query fails
* @see org.springframework.jdbc.core.JdbcTemplate#queryForObject(String, Class)
*/
@Nullable
<T> T queryForObject(String sql, Map<String, ?> paramMap, Class<T> requiredType)
throws DataAccessException;

View File

@@ -28,6 +28,7 @@ import java.util.Set;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -319,7 +320,7 @@ public abstract class NamedParameterUtils {
* @return the array of values
*/
public static Object[] buildValueArray(
ParsedSql parsedSql, SqlParameterSource paramSource, List<SqlParameter> declaredParams) {
ParsedSql parsedSql, SqlParameterSource paramSource, @Nullable List<SqlParameter> declaredParams) {
Object[] paramArray = new Object[parsedSql.getTotalParameterCount()];
if (parsedSql.getNamedParameterCount() > 0 && parsedSql.getUnnamedParameterCount() > 0) {
@@ -352,6 +353,7 @@ public abstract class NamedParameterUtils {
* @param paramIndex the index of the desired parameter
* @return the declared SqlParameter, or {@code null} if none found
*/
@Nullable
private static SqlParameter findParameter(List<SqlParameter> declaredParams, String paramName, int paramIndex) {
if (declaredParams != null) {
// First pass: Look for named parameter match.

View File

@@ -17,6 +17,7 @@
package org.springframework.jdbc.core.namedparam;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.lang.Nullable;
/**
* Interface that defines common functionality for objects that can
@@ -79,6 +80,7 @@ public interface SqlParameterSource {
* @return the type name of the specified parameter,
* or {@code null} if not known
*/
@Nullable
String getTypeName(String paramName);
}

View File

@@ -10,4 +10,7 @@
* the {@code getJdbcOperations()} method of NamedParameterJdbcTemplate and
* work with the returned classic template, or use a JdbcTemplate instance directly.
*/
@NonNullApi
package org.springframework.jdbc.core.namedparam;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* Provides the core JDBC framework, based on JdbcTemplate
* and its associated callback interfaces and helper objects.
*/
@NonNullApi
package org.springframework.jdbc.core;
import org.springframework.lang.NonNullApi;

View File

@@ -5,4 +5,7 @@
* of database metadata provided by the JDBC driver to simplify the application code. Much of the
* parameter specification becomes unnecessary since it can be looked up in the metadata.
*/
@NonNullApi
package org.springframework.jdbc.core.simple;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* Classes supporting the {@code org.springframework.jdbc.core} package.
* Contains a DAO base class for JdbcTemplate usage.
*/
@NonNullApi
package org.springframework.jdbc.core.support;
import org.springframework.lang.NonNullApi;

View File

@@ -20,6 +20,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -105,6 +106,7 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource {
* Return the database catalog to be applied to each Connection, if any.
* @since 4.3.2
*/
@Nullable
public String getCatalog() {
return this.catalog;
}
@@ -122,6 +124,7 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource {
* Return the database schema to be applied to each Connection, if any.
* @since 4.3.2
*/
@Nullable
public String getSchema() {
return this.schema;
}
@@ -141,6 +144,7 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource {
/**
* Return the connection properties to be passed to the Driver, if any.
*/
@Nullable
public Properties getConnectionProperties() {
return this.connectionProperties;
}
@@ -178,7 +182,7 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource {
* @throws SQLException in case of failure
* @see java.sql.Driver#connect(String, java.util.Properties)
*/
protected Connection getConnectionFromDriver(String username, String password) throws SQLException {
protected Connection getConnectionFromDriver(@Nullable String username, @Nullable String password) throws SQLException {
Properties mergedProps = new Properties();
Properties connProps = getConnectionProperties();
if (connProps != null) {

View File

@@ -20,6 +20,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;
import org.springframework.lang.Nullable;
import org.springframework.transaction.support.ResourceHolderSupport;
import org.springframework.util.Assert;
@@ -125,7 +126,7 @@ public class ConnectionHolder extends ResourceHolderSupport {
* <p>Used for releasing the Connection on suspend (with a {@code null}
* argument) and setting a fresh Connection on resume.
*/
protected void setConnection(Connection connection) {
protected void setConnection(@Nullable Connection connection) {
if (this.currentConnection != null) {
this.connectionHandle.releaseConnection(this.currentConnection);
this.currentConnection = null;

View File

@@ -19,12 +19,14 @@ package org.springframework.jdbc.datasource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.lang.Nullable;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@@ -141,6 +143,7 @@ public abstract class DataSourceUtils {
* @throws SQLException if thrown by JDBC methods
* @see #resetConnectionAfterTransaction
*/
@Nullable
public static Integer prepareConnectionForTransaction(Connection con, TransactionDefinition definition)
throws SQLException {
@@ -192,7 +195,7 @@ public abstract class DataSourceUtils {
* @param previousIsolationLevel the isolation level to restore, if any
* @see #prepareConnectionForTransaction
*/
public static void resetConnectionAfterTransaction(Connection con, Integer previousIsolationLevel) {
public static void resetConnectionAfterTransaction(Connection con, @Nullable Integer previousIsolationLevel) {
Assert.notNull(con, "No Connection specified");
try {
// Reset transaction isolation to previous value, if changed for the transaction.
@@ -225,7 +228,7 @@ public abstract class DataSourceUtils {
* (may be {@code null})
* @return whether the Connection is transactional
*/
public static boolean isConnectionTransactional(Connection con, DataSource dataSource) {
public static boolean isConnectionTransactional(Connection con, @Nullable DataSource dataSource) {
if (dataSource == null) {
return false;
}
@@ -277,7 +280,7 @@ public abstract class DataSourceUtils {
* (may be {@code null})
* @see #getConnection
*/
public static void releaseConnection(Connection con, DataSource dataSource) {
public static void releaseConnection(Connection con, @Nullable DataSource dataSource) {
try {
doReleaseConnection(con, dataSource);
}
@@ -300,7 +303,7 @@ public abstract class DataSourceUtils {
* @throws SQLException if thrown by JDBC methods
* @see #doGetConnection
*/
public static void doReleaseConnection(Connection con, DataSource dataSource) throws SQLException {
public static void doReleaseConnection(Connection con, @Nullable DataSource dataSource) throws SQLException {
if (con == null) {
return;
}

View File

@@ -20,6 +20,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import org.springframework.core.Constants;
import org.springframework.lang.Nullable;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@@ -111,6 +112,7 @@ public class IsolationLevelDataSourceAdapter extends UserCredentialsDataSourceAd
* Return the statically specified isolation level,
* or {@code null} if none.
*/
@Nullable
protected Integer getIsolationLevel() {
return this.isolationLevel;
}
@@ -143,6 +145,7 @@ public class IsolationLevelDataSourceAdapter extends UserCredentialsDataSourceAd
* @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionIsolationLevel()
* @see #setIsolationLevel
*/
@Nullable
protected Integer getCurrentIsolationLevel() {
Integer isolationLevelToUse = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (isolationLevelToUse == null) {

View File

@@ -28,6 +28,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.Constants;
import org.springframework.lang.Nullable;
/**
* Proxy for a target DataSource, fetching actual JDBC Connections lazily,
@@ -271,6 +272,7 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource {
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on ConnectionProxy interface coming in...

View File

@@ -24,6 +24,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -146,6 +147,7 @@ public class SingleConnectionDataSource extends DriverManagerDataSource implemen
* Return whether the returned Connection's "autoCommit" setting should be overridden.
* @return the "autoCommit" value, or {@code null} if none to be applied
*/
@Nullable
protected Boolean getAutoCommitValue() {
return this.autoCommit;
}

View File

@@ -25,6 +25,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import org.springframework.lang.Nullable;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
@@ -171,6 +172,7 @@ public class TransactionAwareDataSourceProxy extends DelegatingDataSource {
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on ConnectionProxy interface coming in...

View File

@@ -19,11 +19,13 @@ package org.springframework.jdbc.datasource;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
@@ -157,7 +159,7 @@ public class WebSphereDataSourceAdapter extends IsolationLevelDataSourceAdapter
* @see com.ibm.websphere.rsadapter.JDBCConnectionSpec
*/
protected Object createConnectionSpec(
Integer isolationLevel, Boolean readOnlyFlag, String username, String password) throws SQLException {
@Nullable Integer isolationLevel, @Nullable Boolean readOnlyFlag, @Nullable String username, @Nullable String password) throws SQLException {
Object connSpec = ReflectionUtils.invokeJdbcMethod(this.newJdbcConnSpecMethod, null);
if (isolationLevel != null) {

View File

@@ -21,6 +21,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.UUID;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
@@ -29,6 +30,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -234,6 +236,7 @@ public class EmbeddedDatabaseFactory {
* or if the database has been shut down. Subclasses may call this method to
* access the {@code DataSource} instance directly.
*/
@Nullable
protected final DataSource getDataSource() {
return this.dataSource;
}

View File

@@ -1,4 +1,7 @@
/**
* Provides extensible support for creating embedded database instances.
*/
@NonNullApi
package org.springframework.jdbc.datasource.embedded;
import org.springframework.lang.NonNullApi;

View File

@@ -20,10 +20,12 @@ import java.sql.Connection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -102,7 +104,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
* @since 4.0.3
*/
public ResourceDatabasePopulator(boolean continueOnError, boolean ignoreFailedDrops,
String sqlScriptEncoding, Resource... scripts) {
@Nullable String sqlScriptEncoding, Resource... scripts) {
this(scripts);
this.continueOnError = continueOnError;
@@ -152,7 +154,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
* or empty to indicate platform encoding
* @see #addScript(Resource)
*/
public void setSqlScriptEncoding(String sqlScriptEncoding) {
public void setSqlScriptEncoding(@Nullable String sqlScriptEncoding) {
this.sqlScriptEncoding = StringUtils.hasText(sqlScriptEncoding) ? sqlScriptEncoding : null;
}

View File

@@ -1,4 +1,7 @@
/**
* Provides extensible support for initializing databases through scripts.
*/
@NonNullApi
package org.springframework.jdbc.datasource.init;
import org.springframework.lang.NonNullApi;

View File

@@ -19,8 +19,10 @@ package org.springframework.jdbc.datasource.lookup;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -71,7 +73,7 @@ public class MapDataSourceLookup implements DataSourceLookup {
* call effectively has no effect.
* @param dataSources said {@link Map} of {@link DataSource DataSources}
*/
public void setDataSources(Map<String, DataSource> dataSources) {
public void setDataSources(@Nullable Map<String, DataSource> dataSources) {
if (dataSources != null) {
this.dataSources.putAll(dataSources);
}

View File

@@ -1,4 +1,7 @@
/**
* Provides a strategy for looking up JDBC DataSources by name.
*/
@NonNullApi
package org.springframework.jdbc.datasource.lookup;
import org.springframework.lang.NonNullApi;

View File

@@ -3,4 +3,7 @@
* a PlatformTransactionManager for a single DataSource,
* and various simple DataSource implementations.
*/
@NonNullApi
package org.springframework.jdbc.datasource;
import org.springframework.lang.NonNullApi;

View File

@@ -19,9 +19,11 @@ package org.springframework.jdbc.object;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.lang.Nullable;
/**
* Reusable RDBMS query in which concrete subclasses must implement
@@ -89,7 +91,7 @@ public abstract class MappingSqlQueryWithParameters<T> extends SqlQuery<T> {
* Subclasses can simply not catch SQLExceptions, relying on the
* framework to clean up.
*/
protected abstract T mapRow(ResultSet rs, int rowNum, Object[] parameters, Map<?, ?> context)
protected abstract T mapRow(ResultSet rs, int rowNum, @Nullable Object[] parameters, @Nullable Map<?, ?> context)
throws SQLException;

View File

@@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
@@ -32,6 +33,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.lang.Nullable;
/**
* An "RDBMS operation" is a multi-threaded, reusable object representing a query,
@@ -376,7 +378,7 @@ public abstract class RdbmsOperation implements InitializingBean {
* @param parameters parameters supplied (may be {@code null})
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateParameters(Object[] parameters) throws InvalidDataAccessApiUsageException {
protected void validateParameters(@Nullable Object[] parameters) throws InvalidDataAccessApiUsageException {
checkCompiled();
int declaredInParameters = 0;
for (SqlParameter param : this.declaredParameters) {
@@ -399,7 +401,7 @@ public abstract class RdbmsOperation implements InitializingBean {
* @param parameters parameter Map supplied. May be {@code null}.
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateNamedParameters(Map<String, ?> parameters) throws InvalidDataAccessApiUsageException {
protected void validateNamedParameters(@Nullable Map<String, ?> parameters) throws InvalidDataAccessApiUsageException {
checkCompiled();
Map<String, ?> paramsToUse = (parameters != null ? parameters : Collections.<String, Object> emptyMap());
int declaredInParameters = 0;

View File

@@ -18,12 +18,14 @@ package org.springframework.jdbc.object;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.CallableStatementCreatorFactory;
import org.springframework.jdbc.core.ParameterMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.lang.Nullable;
/**
* RdbmsOperation using a JdbcTemplate and representing a SQL-based
@@ -180,7 +182,7 @@ public abstract class SqlCall extends RdbmsOperation {
* with this parameters.
* @param inParams parameters. May be {@code null}.
*/
protected CallableStatementCreator newCallableStatementCreator(Map<String, ?> inParams) {
protected CallableStatementCreator newCallableStatementCreator(@Nullable Map<String, ?> inParams) {
return this.callableStatementFactory.newCallableStatementCreator(inParams);
}

View File

@@ -21,6 +21,7 @@ import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
import org.springframework.jdbc.core.namedparam.ParsedSql;
import org.springframework.lang.Nullable;
/**
* Operation object representing a SQL-based operation such as a query or update,
@@ -91,7 +92,7 @@ public abstract class SqlOperation extends RdbmsOperation {
* with the given parameters.
* @param params the parameter array (may be {@code null})
*/
protected final PreparedStatementSetter newPreparedStatementSetter(Object[] params) {
protected final PreparedStatementSetter newPreparedStatementSetter(@Nullable Object[] params) {
return this.preparedStatementFactory.newPreparedStatementSetter(params);
}
@@ -100,7 +101,7 @@ public abstract class SqlOperation extends RdbmsOperation {
* with the given parameters.
* @param params the parameter array (may be {@code null})
*/
protected final PreparedStatementCreator newPreparedStatementCreator(Object[] params) {
protected final PreparedStatementCreator newPreparedStatementCreator(@Nullable Object[] params) {
return this.preparedStatementFactory.newPreparedStatementCreator(params);
}
@@ -111,7 +112,7 @@ public abstract class SqlOperation extends RdbmsOperation {
* the factory's, for example because of named parameter expanding)
* @param params the parameter array (may be {@code null})
*/
protected final PreparedStatementCreator newPreparedStatementCreator(String sqlToUse, Object[] params) {
protected final PreparedStatementCreator newPreparedStatementCreator(String sqlToUse, @Nullable Object[] params) {
return this.preparedStatementFactory.newPreparedStatementCreator(sqlToUse, params);
}

View File

@@ -18,6 +18,7 @@ package org.springframework.jdbc.object;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
@@ -26,6 +27,7 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
import org.springframework.jdbc.core.namedparam.ParsedSql;
import org.springframework.lang.Nullable;
/**
* Reusable operation object representing a SQL query.
@@ -247,6 +249,7 @@ public abstract class SqlQuery<T> extends SqlOperation {
* choose to treat this as an error and throw an exception.
* @see org.springframework.dao.support.DataAccessUtils#singleResult
*/
@Nullable
public T findObject(Object[] params, Map<?, ?> context) throws DataAccessException {
List<T> results = execute(params, context);
return DataAccessUtils.singleResult(results);
@@ -357,6 +360,6 @@ public abstract class SqlQuery<T> extends SqlOperation {
* but it can be useful for creating the objects of the result list.
* @see #execute
*/
protected abstract RowMapper<T> newRowMapper(Object[] parameters, Map<?, ?> context);
protected abstract RowMapper<T> newRowMapper(@Nullable Object[] parameters, Map<?, ?> context);
}

View File

@@ -18,6 +18,7 @@ package org.springframework.jdbc.object;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
@@ -25,6 +26,7 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.lang.Nullable;
/**
* Superclass for object abstractions of RDBMS stored procedures.
@@ -109,7 +111,7 @@ public abstract class StoredProcedure extends SqlCall {
* Output parameters will appear here, with their values after the
* stored procedure has been called.
*/
public Map<String, Object> execute(Object... inParams) {
public Map<String, Object> execute(@Nullable Object... inParams) {
Map<String, Object> paramsToUse = new HashMap<>();
validateParameters(inParams);
int i = 0;
@@ -137,7 +139,7 @@ public abstract class StoredProcedure extends SqlCall {
* Output parameters will appear here, with their values after the
* stored procedure has been called.
*/
public Map<String, Object> execute(Map<String, ?> inParams) throws DataAccessException {
public Map<String, Object> execute(@Nullable Map<String, ?> inParams) throws DataAccessException {
validateParameters(inParams.values().toArray());
return getJdbcTemplate().call(newCallableStatementCreator(inParams), getDeclaredParameters());
}
@@ -158,7 +160,7 @@ public abstract class StoredProcedure extends SqlCall {
* Output parameters will appear here, with their values after the
* stored procedure has been called.
*/
public Map<String, Object> execute(ParameterMapper inParamMapper) throws DataAccessException {
public Map<String, Object> execute(@Nullable ParameterMapper inParamMapper) throws DataAccessException {
checkCompiled();
return getJdbcTemplate().call(newCallableStatementCreator(inParamMapper), getDeclaredParameters());
}

View File

@@ -19,9 +19,11 @@ package org.springframework.jdbc.object;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.lang.Nullable;
/**
* Reusable RDBMS query in which concrete subclasses must implement
@@ -78,7 +80,7 @@ public abstract class UpdatableSqlQuery<T> extends SqlQuery<T> {
* Subclasses can simply not catch SQLExceptions, relying on the
* framework to clean up.
*/
protected abstract T updateRow(ResultSet rs, int rowNum, Map<?, ?> context) throws SQLException;
protected abstract T updateRow(ResultSet rs, int rowNum, @Nullable Map<?, ?> context) throws SQLException;
/**

View File

@@ -14,4 +14,7 @@
* <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0764543857/">Expert One-On-One J2EE Design and Development</a>
* by Rod Johnson (Wrox, 2002).
*/
@NonNullApi
package org.springframework.jdbc.object;
import org.springframework.lang.NonNullApi;

View File

@@ -17,4 +17,7 @@
* <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0764543857/">Expert One-On-One J2EE Design and Development</a>
* by Rod Johnson (Wrox, 2002).
*/
@NonNullApi
package org.springframework.jdbc;
import org.springframework.lang.NonNullApi;

View File

@@ -23,6 +23,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -51,6 +52,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
/**
* Return the fallback exception translator, if any.
*/
@Nullable
public SQLExceptionTranslator getFallbackTranslator() {
return this.fallbackTranslator;
}
@@ -95,7 +97,8 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
* @return the DataAccessException, wrapping the {@code SQLException};
* or {@code null} if no exception match found
*/
protected abstract DataAccessException doTranslate(String task, String sql, SQLException ex);
@Nullable
protected abstract DataAccessException doTranslate(String task, @Nullable String sql, SQLException ex);
/**
@@ -107,7 +110,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
* @param ex the offending {@code SQLException}
* @return the message {@code String} to use
*/
protected String buildMessage(String task, String sql, SQLException ex) {
protected String buildMessage(String task, @Nullable String sql, SQLException ex) {
return task + "; SQL [" + sql + "]; " + ex.getMessage();
}

View File

@@ -22,6 +22,8 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
/**
* Registry for custom {@link org.springframework.jdbc.support.SQLExceptionTranslator} instances associated with
* specific databases allowing for overriding translation based on values contained in the configuration file
@@ -86,6 +88,7 @@ public class CustomSQLExceptionTranslatorRegistry {
* @param dbName the database name
* @return the custom translator, or {@code null} if none found
*/
@Nullable
public SQLExceptionTranslator findTranslatorForDatabase(String dbName) {
return this.translatorMap.get(dbName);
}

View File

@@ -29,6 +29,7 @@ import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.sql.Types;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
@@ -36,6 +37,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.NumberUtils;
/**
@@ -61,7 +63,7 @@ public abstract class JdbcUtils {
* This is useful for typical finally blocks in manual JDBC code.
* @param con the JDBC Connection to close (may be {@code null})
*/
public static void closeConnection(Connection con) {
public static void closeConnection(@Nullable Connection con) {
if (con != null) {
try {
con.close();
@@ -81,7 +83,7 @@ public abstract class JdbcUtils {
* This is useful for typical finally blocks in manual JDBC code.
* @param stmt the JDBC Statement to close (may be {@code null})
*/
public static void closeStatement(Statement stmt) {
public static void closeStatement(@Nullable Statement stmt) {
if (stmt != null) {
try {
stmt.close();
@@ -101,7 +103,7 @@ public abstract class JdbcUtils {
* This is useful for typical finally blocks in manual JDBC code.
* @param rs the JDBC ResultSet to close (may be {@code null})
*/
public static void closeResultSet(ResultSet rs) {
public static void closeResultSet(@Nullable ResultSet rs) {
if (rs != null) {
try {
rs.close();
@@ -131,7 +133,7 @@ public abstract class JdbcUtils {
* @throws SQLException if thrown by the JDBC API
* @see #getResultSetValue(ResultSet, int)
*/
public static Object getResultSetValue(ResultSet rs, int index, Class<?> requiredType) throws SQLException {
public static Object getResultSetValue(ResultSet rs, int index, @Nullable Class<?> requiredType) throws SQLException {
if (requiredType == null) {
return getResultSetValue(rs, index);
}

View File

@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Map;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.lang.Nullable;
/**
* Interface for retrieving keys, typically used for auto-generated keys
@@ -54,6 +55,7 @@ public interface KeyHolder {
* @return the generated key
* @throws InvalidDataAccessApiUsageException if multiple keys are encountered.
*/
@Nullable
Number getKey() throws InvalidDataAccessApiUsageException;
/**
@@ -63,6 +65,7 @@ public interface KeyHolder {
* @return the Map of generated keys
* @throws InvalidDataAccessApiUsageException if keys for multiple rows are encountered
*/
@Nullable
Map<String, Object> getKeys() throws InvalidDataAccessApiUsageException;
/**

View File

@@ -20,6 +20,7 @@ import java.lang.reflect.Constructor;
import java.sql.BatchUpdateException;
import java.sql.SQLException;
import java.util.Arrays;
import javax.sql.DataSource;
import org.springframework.dao.CannotAcquireLockException;
@@ -33,6 +34,7 @@ import org.springframework.dao.PermissionDeniedDataAccessException;
import org.springframework.dao.TransientDataAccessResourceException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.InvalidResultSetAccessException;
import org.springframework.lang.Nullable;
/**
* Implementation of {@link SQLExceptionTranslator} that analyzes vendor-specific error codes.
@@ -295,7 +297,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
* as a nested root cause. This implementation always returns null, meaning that
* the translator always falls back to the default error codes.
*/
protected DataAccessException customTranslate(String task, String sql, SQLException sqlEx) {
protected DataAccessException customTranslate(String task, @Nullable String sql, SQLException sqlEx) {
return null;
}
@@ -313,7 +315,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
* @see CustomSQLErrorCodesTranslation#setExceptionClass
*/
protected DataAccessException createCustomException(
String task, String sql, SQLException sqlEx, Class<?> exceptionClass) {
String task, @Nullable String sql, SQLException sqlEx, Class<?> exceptionClass) {
// find appropriate constructor
try {

View File

@@ -18,6 +18,7 @@ package org.springframework.jdbc.support;
import java.util.Collections;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
@@ -28,6 +29,7 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.PatternMatchUtils;
@@ -145,6 +147,7 @@ public class SQLErrorCodesFactory {
* @return the resource, or {@code null} if the resource wasn't found
* @see #getInstance
*/
@Nullable
protected Resource loadResource(String path) {
return new ClassPathResource(path, getClass().getClassLoader());
}
@@ -255,6 +258,7 @@ public class SQLErrorCodesFactory {
* @since 4.3.5
* @see #registerDatabase(DataSource, String)
*/
@Nullable
public SQLErrorCodes unregisterDatabase(DataSource dataSource) {
return this.dataSourceCache.remove(dataSource);
}

View File

@@ -19,6 +19,7 @@ package org.springframework.jdbc.support;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Strategy interface for translating between {@link SQLException SQLExceptions}
@@ -50,6 +51,7 @@ public interface SQLExceptionTranslator {
* @return the DataAccessException, wrapping the {@code SQLException}
* @see org.springframework.dao.DataAccessException#getRootCause()
*/
DataAccessException translate(String task, String sql, SQLException ex);
@Nullable
DataAccessException translate(String task, @Nullable String sql, SQLException ex);
}

View File

@@ -22,6 +22,8 @@ import java.io.Reader;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.springframework.lang.Nullable;
/**
* Interface that abstracts potentially database-specific creation of large binary
* fields and large text fields. Does not work with {@code java.sql.Blob}
@@ -68,7 +70,7 @@ public interface LobCreator extends Closeable {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.PreparedStatement#setBytes
*/
void setBlobAsBytes(PreparedStatement ps, int paramIndex, byte[] content)
void setBlobAsBytes(PreparedStatement ps, int paramIndex, @Nullable byte[] content)
throws SQLException;
/**
@@ -82,7 +84,7 @@ public interface LobCreator extends Closeable {
* @see java.sql.PreparedStatement#setBinaryStream
*/
void setBlobAsBinaryStream(
PreparedStatement ps, int paramIndex, InputStream contentStream, int contentLength)
PreparedStatement ps, int paramIndex, @Nullable InputStream contentStream, int contentLength)
throws SQLException;
/**
@@ -95,7 +97,7 @@ public interface LobCreator extends Closeable {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.PreparedStatement#setBytes
*/
void setClobAsString(PreparedStatement ps, int paramIndex, String content)
void setClobAsString(PreparedStatement ps, int paramIndex, @Nullable String content)
throws SQLException;
/**
@@ -109,7 +111,7 @@ public interface LobCreator extends Closeable {
* @see java.sql.PreparedStatement#setAsciiStream
*/
void setClobAsAsciiStream(
PreparedStatement ps, int paramIndex, InputStream asciiStream, int contentLength)
PreparedStatement ps, int paramIndex, @Nullable InputStream asciiStream, int contentLength)
throws SQLException;
/**
@@ -123,7 +125,7 @@ public interface LobCreator extends Closeable {
* @see java.sql.PreparedStatement#setCharacterStream
*/
void setClobAsCharacterStream(
PreparedStatement ps, int paramIndex, Reader characterStream, int contentLength)
PreparedStatement ps, int paramIndex, @Nullable Reader characterStream, int contentLength)
throws SQLException;
/**

View File

@@ -21,6 +21,8 @@ import java.io.Reader;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.lang.Nullable;
/**
* Abstraction for handling large binary fields and large text fields in
* specific databases, no matter if represented as simple types or Large OBjects.
@@ -83,6 +85,7 @@ public interface LobHandler {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getBytes
*/
@Nullable
byte[] getBlobAsBytes(ResultSet rs, String columnName) throws SQLException;
/**
@@ -95,6 +98,7 @@ public interface LobHandler {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getBytes
*/
@Nullable
byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException;
/**
@@ -107,6 +111,7 @@ public interface LobHandler {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getBinaryStream
*/
@Nullable
InputStream getBlobAsBinaryStream(ResultSet rs, String columnName) throws SQLException;
/**
@@ -119,6 +124,7 @@ public interface LobHandler {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getBinaryStream
*/
@Nullable
InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException;
/**
@@ -131,6 +137,7 @@ public interface LobHandler {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getString
*/
@Nullable
String getClobAsString(ResultSet rs, String columnName) throws SQLException;
/**
@@ -143,6 +150,7 @@ public interface LobHandler {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getString
*/
@Nullable
String getClobAsString(ResultSet rs, int columnIndex) throws SQLException;
/**
@@ -155,6 +163,7 @@ public interface LobHandler {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getAsciiStream
*/
@Nullable
InputStream getClobAsAsciiStream(ResultSet rs, String columnName) throws SQLException;
/**
@@ -167,6 +176,7 @@ public interface LobHandler {
* @throws SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getAsciiStream
*/
@Nullable
InputStream getClobAsAsciiStream(ResultSet rs, int columnIndex) throws SQLException;
/**

View File

@@ -2,4 +2,7 @@
* Provides a strategy interface for Large OBject handling,
* as well as a customizable default implementation.
*/
@NonNullApi
package org.springframework.jdbc.support.lob;
import org.springframework.lang.NonNullApi;

View File

@@ -6,4 +6,7 @@
* <p>Can be used independently, for example in custom JDBC access code,
* or in JDBC-based O/R mapping layers.
*/
@NonNullApi
package org.springframework.jdbc.support;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* Provides a convenient holder for disconnected result sets.
* Supported by JdbcTemplate, but can be used independently too.
*/
@NonNullApi
package org.springframework.jdbc.support.rowset;
import org.springframework.lang.NonNullApi;

View File

@@ -20,11 +20,14 @@ import java.io.InputStream;
import java.io.Reader;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import org.w3c.dom.Document;
import org.springframework.lang.Nullable;
/**
* Abstraction for handling XML fields in specific databases. Its main purpose
* is to isolate database-specific handling of XML stored in the database.
@@ -61,6 +64,7 @@ public interface SqlXmlHandler {
* @see java.sql.ResultSet#getString
* @see java.sql.ResultSet#getSQLXML
*/
@Nullable
String getXmlAsString(ResultSet rs, String columnName) throws SQLException;
/**
@@ -75,6 +79,7 @@ public interface SqlXmlHandler {
* @see java.sql.ResultSet#getString
* @see java.sql.ResultSet#getSQLXML
*/
@Nullable
String getXmlAsString(ResultSet rs, int columnIndex) throws SQLException;
/**
@@ -89,6 +94,7 @@ public interface SqlXmlHandler {
* @see java.sql.ResultSet#getSQLXML
* @see java.sql.SQLXML#getBinaryStream
*/
@Nullable
InputStream getXmlAsBinaryStream(ResultSet rs, String columnName) throws SQLException;
/**
@@ -103,6 +109,7 @@ public interface SqlXmlHandler {
* @see java.sql.ResultSet#getSQLXML
* @see java.sql.SQLXML#getBinaryStream
*/
@Nullable
InputStream getXmlAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException;
/**
@@ -117,6 +124,7 @@ public interface SqlXmlHandler {
* @see java.sql.ResultSet#getSQLXML
* @see java.sql.SQLXML#getCharacterStream
*/
@Nullable
Reader getXmlAsCharacterStream(ResultSet rs, String columnName) throws SQLException;
/**
@@ -131,6 +139,7 @@ public interface SqlXmlHandler {
* @see java.sql.ResultSet#getSQLXML
* @see java.sql.SQLXML#getCharacterStream
*/
@Nullable
Reader getXmlAsCharacterStream(ResultSet rs, int columnIndex) throws SQLException;
/**
@@ -146,6 +155,7 @@ public interface SqlXmlHandler {
* @see java.sql.ResultSet#getSQLXML
* @see java.sql.SQLXML#getSource
*/
@Nullable
Source getXmlAsSource(ResultSet rs, String columnName, Class<? extends Source> sourceClass) throws SQLException;
/**
@@ -161,6 +171,7 @@ public interface SqlXmlHandler {
* @see java.sql.ResultSet#getSQLXML
* @see java.sql.SQLXML#getSource
*/
@Nullable
Source getXmlAsSource(ResultSet rs, int columnIndex, Class<? extends Source> sourceClass) throws SQLException;

View File

@@ -19,6 +19,8 @@ package org.springframework.jdbc.support.xml;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.lang.Nullable;
/**
* Abstraction for handling XML object mapping to fields in a database.
*
@@ -43,6 +45,7 @@ public interface SqlXmlObjectMappingHandler extends SqlXmlHandler {
* @throws java.sql.SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getSQLXML
*/
@Nullable
Object getXmlAsObject(ResultSet rs, String columnName) throws SQLException;
/**
@@ -55,6 +58,7 @@ public interface SqlXmlObjectMappingHandler extends SqlXmlHandler {
* @throws java.sql.SQLException if thrown by JDBC methods
* @see java.sql.ResultSet#getSQLXML
*/
@Nullable
Object getXmlAsObject(ResultSet rs, int columnIndex) throws SQLException;
/**

View File

@@ -1,4 +1,7 @@
/**
* Abstraction for handling fields of SQLXML data type.
*/
@NonNullApi
package org.springframework.jdbc.support.xml;
import org.springframework.lang.NonNullApi;