diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java index c615fac24d1..a5f0486638e 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 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. @@ -261,7 +261,7 @@ public class BeanPropertyRowMapper implements RowMapper { * @param propertyName the property name (as used by property descriptors) * @since 5.3.9 */ - protected void suppressProperty(String propertyName) { + protected void suppressProperty(@Nullable String propertyName) { if (this.mappedProperties != null) { this.mappedProperties.remove(lowerCaseName(propertyName)); this.mappedProperties.remove(underscoreName(propertyName)); @@ -296,7 +296,10 @@ public class BeanPropertyRowMapper implements RowMapper { * @since 4.2 * @see #underscoreName */ - protected String lowerCaseName(String name) { + protected String lowerCaseName(@Nullable String name) { + if (!StringUtils.hasLength(name)) { + return ""; + } return name.toLowerCase(Locale.US); } @@ -308,7 +311,7 @@ public class BeanPropertyRowMapper implements RowMapper { * @since 4.2 * @see JdbcUtils#convertPropertyNameToUnderscoreName */ - protected String underscoreName(String name) { + protected String underscoreName(@Nullable String name) { return JdbcUtils.convertPropertyNameToUnderscoreName(name); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/DataClassRowMapper.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/DataClassRowMapper.java index b14bf961cc4..1cdb14a4e44 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/DataClassRowMapper.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/DataClassRowMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 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. @@ -64,7 +64,7 @@ public class DataClassRowMapper extends BeanPropertyRowMapper { private @Nullable Constructor mappedConstructor; - private String @Nullable [] constructorParameterNames; + private @Nullable String @Nullable [] constructorParameterNames; private TypeDescriptor @Nullable [] constructorParameterTypes; @@ -108,7 +108,7 @@ public class DataClassRowMapper extends BeanPropertyRowMapper { protected T constructMappedInstance(ResultSet rs, TypeConverter tc) throws SQLException { Assert.state(this.mappedConstructor != null, "Mapped constructor was not initialized"); - Object[] args; + @Nullable Object[] args; if (this.constructorParameterNames != null && this.constructorParameterTypes != null) { args = new Object[this.constructorParameterNames.length]; for (int i = 0; i < args.length; i++) { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementCreatorFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementCreatorFactory.java index f98468641d0..6d174ad8048 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementCreatorFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementCreatorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 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. @@ -154,7 +154,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 @Nullable [] params) { + public PreparedStatementSetter newPreparedStatementSetter(@Nullable Object @Nullable [] params) { return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.emptyList()); } @@ -162,7 +162,7 @@ public class PreparedStatementCreatorFactory { * Return a new PreparedStatementCreator for the given parameters. * @param params list of parameters (may be {@code null}) */ - public PreparedStatementCreator newPreparedStatementCreator(@Nullable List params) { + public PreparedStatementCreator newPreparedStatementCreator(@Nullable List params) { return new PreparedStatementCreatorImpl(params != null ? params : Collections.emptyList()); } @@ -170,7 +170,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 @Nullable [] params) { + public PreparedStatementCreator newPreparedStatementCreator(@Nullable Object @Nullable [] params) { return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.emptyList()); } @@ -180,7 +180,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 @Nullable [] params) { + public PreparedStatementCreator newPreparedStatementCreator(String sqlToUse, @Nullable Object @Nullable [] params) { return new PreparedStatementCreatorImpl( sqlToUse, (params != null ? Arrays.asList(params) : Collections.emptyList())); } @@ -208,7 +208,7 @@ public class PreparedStatementCreatorFactory { Set names = new HashSet<>(); for (int i = 0; i < parameters.size(); i++) { Object param = parameters.get(i); - if (param instanceof SqlParameterValue sqlParameterValue) { + if (param instanceof SqlParameterValue sqlParameterValue && sqlParameterValue.getName() != null) { names.add(sqlParameterValue.getName()); } else { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SimplePropertyRowMapper.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SimplePropertyRowMapper.java index e15c8e21e3a..c5e59763ded 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SimplePropertyRowMapper.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SimplePropertyRowMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 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. @@ -28,6 +28,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.BeanUtils; import org.springframework.core.MethodParameter; import org.springframework.core.convert.ConversionService; @@ -82,7 +84,7 @@ public class SimplePropertyRowMapper implements RowMapper { private final Constructor mappedConstructor; - private final String[] constructorParameterNames; + private final @Nullable String[] constructorParameterNames; private final TypeDescriptor[] constructorParameterTypes; @@ -122,7 +124,7 @@ public class SimplePropertyRowMapper implements RowMapper { @Override public T mapRow(ResultSet rs, int rowNumber) throws SQLException { - Object[] args = new Object[this.constructorParameterNames.length]; + @Nullable Object[] args = new Object[this.constructorParameterNames.length]; Set usedIndex = new HashSet<>(); for (int i = 0; i < args.length; i++) { String name = this.constructorParameterNames[i]; diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java index ec51624fe0d..2a9e9489294 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 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. @@ -370,7 +370,7 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { - Object[] values = NamedParameterUtils.buildValueArray(parsedSql, batchArgs[i], null); + @Nullable Object[] values = NamedParameterUtils.buildValueArray(parsedSql, batchArgs[i], null); pscf.newPreparedStatementSetter(values).setValues(ps); } @Override @@ -407,12 +407,12 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations else { pscf.setReturnGeneratedKeys(true); } - Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); + @Nullable Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); PreparedStatementCreator psc = pscf.newPreparedStatementCreator(params); return getJdbcOperations().batchUpdate(psc, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { - Object[] values = NamedParameterUtils.buildValueArray(parsedSql, batchArgs[i], null); + @Nullable Object[] values = NamedParameterUtils.buildValueArray(parsedSql, batchArgs[i], null); pscf.newPreparedStatementSetter(values).setValues(ps); } @@ -460,7 +460,7 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations if (customizer != null) { customizer.accept(pscf); } - Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); + @Nullable Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); return pscf.newPreparedStatementCreator(params); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java index 750cf85ad00..6df168ae65d 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 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. @@ -348,10 +348,10 @@ public abstract class NamedParameterUtils { * be built into the value array in the form of SqlParameterValue objects. * @return the array of values */ - public static Object[] buildValueArray( + public static @Nullable Object[] buildValueArray( ParsedSql parsedSql, SqlParameterSource paramSource, @Nullable List declaredParams) { - Object[] paramArray = new Object[parsedSql.getTotalParameterCount()]; + @Nullable Object[] paramArray = new Object[parsedSql.getTotalParameterCount()]; if (parsedSql.getNamedParameterCount() > 0 && parsedSql.getUnnamedParameterCount() > 0) { throw new InvalidDataAccessApiUsageException( "Not allowed to mix named and traditional ? placeholders. You have " + @@ -497,7 +497,7 @@ public abstract class NamedParameterUtils { * @param paramMap the Map of parameters * @return the array of values */ - public static Object[] buildValueArray(String sql, Map paramMap) { + public static @Nullable Object[] buildValueArray(String sql, Map paramMap) { ParsedSql parsedSql = parseSqlStatement(sql); return buildValueArray(parsedSql, new MapSqlParameterSource(paramMap), null); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/GenericSqlQuery.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/GenericSqlQuery.java index fd9f17ac069..db4341ce152 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/GenericSqlQuery.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/GenericSqlQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2025 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. @@ -70,7 +70,7 @@ public class GenericSqlQuery extends SqlQuery { @Override @SuppressWarnings("unchecked") - protected RowMapper newRowMapper(Object @Nullable [] parameters, @Nullable Map context) { + protected RowMapper newRowMapper(@Nullable Object @Nullable [] parameters, @Nullable Map context) { if (this.rowMapper != null) { return this.rowMapper; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQuery.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQuery.java index b10136dca5b..096896db00c 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQuery.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2025 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. @@ -63,7 +63,7 @@ public abstract class MappingSqlQuery extends MappingSqlQueryWithParameters context) + protected final @Nullable T mapRow(ResultSet rs, int rowNum, @Nullable Object @Nullable [] parameters, @Nullable Map context) throws SQLException { return mapRow(rs, rowNum); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQueryWithParameters.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQueryWithParameters.java index 94727f0ee99..f631e1008d8 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQueryWithParameters.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQueryWithParameters.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2025 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. @@ -74,7 +74,7 @@ public abstract class MappingSqlQueryWithParameters extends SqlQuery { * implementation of the mapRow() method. */ @Override - protected RowMapper newRowMapper(Object @Nullable [] parameters, @Nullable Map context) { + protected RowMapper newRowMapper(@Nullable Object @Nullable [] parameters, @Nullable Map context) { return new RowMapperImpl(parameters, context); } @@ -93,7 +93,7 @@ public abstract class MappingSqlQueryWithParameters extends SqlQuery { * Subclasses can simply not catch SQLExceptions, relying on the * framework to clean up. */ - protected abstract @Nullable T mapRow(ResultSet rs, int rowNum, Object @Nullable [] parameters, @Nullable Map context) + protected abstract @Nullable T mapRow(ResultSet rs, int rowNum, @Nullable Object @Nullable [] parameters, @Nullable Map context) throws SQLException; @@ -103,14 +103,14 @@ public abstract class MappingSqlQueryWithParameters extends SqlQuery { */ protected class RowMapperImpl implements RowMapper { - private final Object @Nullable [] params; + private final @Nullable Object @Nullable [] params; private final @Nullable Map context; /** * Use an array results. More efficient if we know how many results to expect. */ - public RowMapperImpl(Object @Nullable [] parameters, @Nullable Map context) { + public RowMapperImpl(@Nullable Object @Nullable [] parameters, @Nullable Map context) { this.params = parameters; this.context = context; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlOperation.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlOperation.java index de6e8173741..0aa1efea040 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlOperation.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2025 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. @@ -94,7 +94,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 @Nullable [] params) { + protected final PreparedStatementSetter newPreparedStatementSetter(@Nullable Object @Nullable [] params) { Assert.state(this.preparedStatementFactory != null, "No PreparedStatementFactory available"); return this.preparedStatementFactory.newPreparedStatementSetter(params); } @@ -104,7 +104,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 @Nullable [] params) { + protected final PreparedStatementCreator newPreparedStatementCreator(@Nullable Object @Nullable [] params) { Assert.state(this.preparedStatementFactory != null, "No PreparedStatementFactory available"); return this.preparedStatementFactory.newPreparedStatementCreator(params); } @@ -116,7 +116,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 @Nullable [] params) { + protected final PreparedStatementCreator newPreparedStatementCreator(String sqlToUse, @Nullable Object @Nullable [] params) { Assert.state(this.preparedStatementFactory != null, "No PreparedStatementFactory available"); return this.preparedStatementFactory.newPreparedStatementCreator(sqlToUse, params); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlQuery.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlQuery.java index ad0d7b03c2e..88084cc62d4 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlQuery.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2025 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. @@ -227,7 +227,7 @@ public abstract class SqlQuery extends SqlOperation { ParsedSql parsedSql = getParsedSql(); MapSqlParameterSource paramSource = new MapSqlParameterSource(paramMap); String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource); - Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters()); + @Nullable Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters()); RowMapper rowMapper = newRowMapper(params, context); return getJdbcTemplate().query(newPreparedStatementCreator(sqlToUse, params), rowMapper); } @@ -238,7 +238,7 @@ public abstract class SqlQuery extends SqlOperation { * the SqlParameters. Primitive parameters must be represented by their Object wrapper * type. The ordering of parameters is not significant. */ - public List executeByNamedParam(Map paramMap) throws DataAccessException { + public List executeByNamedParam(Map paramMap) throws DataAccessException { return executeByNamedParam(paramMap, null); } @@ -361,6 +361,6 @@ public abstract class SqlQuery extends SqlOperation { * but it can be useful for creating the objects of the result list. * @see #execute */ - protected abstract RowMapper newRowMapper(Object @Nullable [] parameters, @Nullable Map context); + protected abstract RowMapper newRowMapper(@Nullable Object @Nullable [] parameters, @Nullable Map context); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlUpdate.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlUpdate.java index a68e87c14cd..f85358ea808 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlUpdate.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlUpdate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ import java.util.Map; import javax.sql.DataSource; +import org.jspecify.annotations.Nullable; + import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException; @@ -252,7 +254,7 @@ public class SqlUpdate extends SqlOperation { ParsedSql parsedSql = getParsedSql(); MapSqlParameterSource paramSource = new MapSqlParameterSource(paramMap); String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource); - Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters()); + @Nullable Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters()); int rowsAffected = getJdbcTemplate().update(newPreparedStatementCreator(sqlToUse, params)); checkRowsAffected(rowsAffected); return rowsAffected; @@ -271,7 +273,7 @@ public class SqlUpdate extends SqlOperation { ParsedSql parsedSql = getParsedSql(); MapSqlParameterSource paramSource = new MapSqlParameterSource(paramMap); String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource); - Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters()); + @Nullable Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters()); int rowsAffected = getJdbcTemplate().update(newPreparedStatementCreator(sqlToUse, params), generatedKeyHolder); checkRowsAffected(rowsAffected); return rowsAffected; diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/UpdatableSqlQuery.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/UpdatableSqlQuery.java index 9e4e3ad1a9b..d2fef590b62 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/UpdatableSqlQuery.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/UpdatableSqlQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2025 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. @@ -63,7 +63,7 @@ public abstract class UpdatableSqlQuery extends SqlQuery { * implementation of the {@code updateRow()} method. */ @Override - protected RowMapper newRowMapper(Object @Nullable [] parameters, @Nullable Map context) { + protected RowMapper newRowMapper(@Nullable Object @Nullable [] parameters, @Nullable Map context) { return new RowMapperImpl(context); }