Merge branch '6.0.x'

This commit is contained in:
Juergen Hoeller 2023-07-26 12:08:20 +02:00
commit 3437e61f98
9 changed files with 62 additions and 73 deletions

View File

@ -19,13 +19,13 @@ package org.springframework.scheduling.support;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.scheduling.Trigger; import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext; import org.springframework.scheduling.TriggerContext;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/** /**
* A trigger for periodic task execution. The period may be applied as either * A trigger for periodic task execution. The period may be applied as either
@ -250,7 +250,7 @@ public class PeriodicTrigger implements Trigger {
return (this == other || (other instanceof PeriodicTrigger that && return (this == other || (other instanceof PeriodicTrigger that &&
this.fixedRate == that.fixedRate && this.fixedRate == that.fixedRate &&
this.period.equals(that.period) && this.period.equals(that.period) &&
Objects.equals(this.initialDelay, that.initialDelay))); ObjectUtils.nullSafeEquals(this.initialDelay, that.initialDelay)));
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -43,7 +43,7 @@ import org.springframework.util.StringUtils;
* Abstract class to provide base functionality for easy stored procedure calls * Abstract class to provide base functionality for easy stored procedure calls
* based on configuration options and database meta-data. * based on configuration options and database meta-data.
* *
* <p>This class provides the base SPI for {@link SimpleJdbcCall}. * <p>This class provides the processing arrangement for {@link SimpleJdbcCall}.
* *
* @author Thomas Risberg * @author Thomas Risberg
* @author Juergen Hoeller * @author Juergen Hoeller
@ -453,7 +453,7 @@ public abstract class AbstractJdbcCall {
/** /**
* Match the provided in parameter values with registered parameters and * Match the provided in parameter values with registered parameters and
* parameters defined via meta-data processing. * parameters defined via meta-data processing.
* @param args the parameter values provided in a Map * @param args the parameter values provided as a Map
* @return a Map with parameter names and values * @return a Map with parameter names and values
*/ */
protected Map<String, ?> matchInParameterValuesWithCallParameters(Map<String, ?> args) { protected Map<String, ?> matchInParameterValuesWithCallParameters(Map<String, ?> args) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -50,10 +50,10 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Abstract class to provide base functionality for easy inserts * Abstract class to provide base functionality for easy (batch) inserts
* based on configuration options and database meta-data. * based on configuration options and database meta-data.
* *
* <p>This class provides the base SPI for {@link SimpleJdbcInsert}. * <p>This class provides the processing arrangement for {@link SimpleJdbcInsert}.
* *
* @author Thomas Risberg * @author Thomas Risberg
* @author Juergen Hoeller * @author Juergen Hoeller
@ -409,7 +409,7 @@ public abstract class AbstractJdbcInsert {
/** /**
* Delegate method to execute the insert, generating a single key. * Delegate method to execute the insert, generating a single key.
*/ */
private Number executeInsertAndReturnKeyInternal(final List<?> values) { private Number executeInsertAndReturnKeyInternal(List<?> values) {
KeyHolder kh = executeInsertAndReturnKeyHolderInternal(values); KeyHolder kh = executeInsertAndReturnKeyHolderInternal(values);
if (kh.getKey() != null) { if (kh.getKey() != null) {
return kh.getKey(); return kh.getKey();
@ -423,11 +423,11 @@ public abstract class AbstractJdbcInsert {
/** /**
* Delegate method to execute the insert, generating any number of keys. * Delegate method to execute the insert, generating any number of keys.
*/ */
private KeyHolder executeInsertAndReturnKeyHolderInternal(final List<?> values) { private KeyHolder executeInsertAndReturnKeyHolderInternal(List<?> values) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("The following parameters are used for call " + getInsertString() + " with: " + values); logger.debug("The following parameters are used for call " + getInsertString() + " with: " + values);
} }
final KeyHolder keyHolder = new GeneratedKeyHolder(); KeyHolder keyHolder = new GeneratedKeyHolder();
if (this.tableMetaDataContext.isGetGeneratedKeysSupported()) { if (this.tableMetaDataContext.isGetGeneratedKeysSupported()) {
getJdbcTemplate().update( getJdbcTemplate().update(
@ -455,7 +455,7 @@ public abstract class AbstractJdbcInsert {
} }
Assert.state(getTableName() != null, "No table name set"); Assert.state(getTableName() != null, "No table name set");
final String keyQuery = this.tableMetaDataContext.getSimpleQueryForGetGeneratedKey( String keyQuery = this.tableMetaDataContext.getSimpleQueryForGetGeneratedKey(
getTableName(), getGeneratedKeyNames()[0]); getTableName(), getGeneratedKeyNames()[0]);
Assert.state(keyQuery != null, "Query for simulating get generated keys must not be null"); Assert.state(keyQuery != null, "Query for simulating get generated keys must not be null");
@ -535,8 +535,8 @@ public abstract class AbstractJdbcInsert {
/** /**
* Delegate method that executes a batch insert using the passed-in Maps of parameters. * Delegate method that executes a batch insert using the passed-in Maps of parameters.
* @param batch array of Maps with parameter names and values to be used in batch insert * @param batch maps with parameter names and values to be used in the batch insert
* @return array of number of rows affected * @return an array of number of rows affected
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected int[] doExecuteBatch(Map<String, ?>... batch) { protected int[] doExecuteBatch(Map<String, ?>... batch) {
@ -549,9 +549,10 @@ public abstract class AbstractJdbcInsert {
} }
/** /**
* Delegate method that executes a batch insert using the passed-in {@link SqlParameterSource SqlParameterSources}. * Delegate method that executes a batch insert using the passed-in
* @param batch array of SqlParameterSource with parameter names and values to be used in insert * {@link SqlParameterSource SqlParameterSources}.
* @return array of number of rows affected * @param batch parameter sources with names and values to be used in the batch insert
* @return an array of number of rows affected
*/ */
protected int[] doExecuteBatch(SqlParameterSource... batch) { protected int[] doExecuteBatch(SqlParameterSource... batch) {
checkCompiled(); checkCompiled();
@ -606,7 +607,7 @@ public abstract class AbstractJdbcInsert {
* Match the provided in parameter values with registered parameters and parameters * Match the provided in parameter values with registered parameters and parameters
* defined via meta-data processing. * defined via meta-data processing.
* @param parameterSource the parameter values provided as a {@link SqlParameterSource} * @param parameterSource the parameter values provided as a {@link SqlParameterSource}
* @return a Map with parameter names and values * @return a List of values
*/ */
protected List<Object> matchInParameterValuesWithInsertColumns(SqlParameterSource parameterSource) { protected List<Object> matchInParameterValuesWithInsertColumns(SqlParameterSource parameterSource) {
return this.tableMetaDataContext.matchInParameterValuesWithInsertColumns(parameterSource); return this.tableMetaDataContext.matchInParameterValuesWithInsertColumns(parameterSource);
@ -615,8 +616,8 @@ public abstract class AbstractJdbcInsert {
/** /**
* Match the provided in parameter values with registered parameters and parameters * Match the provided in parameter values with registered parameters and parameters
* defined via meta-data processing. * defined via meta-data processing.
* @param args the parameter values provided in a Map * @param args the parameter values provided as a Map
* @return a Map with parameter names and values * @return a List of values
*/ */
protected List<Object> matchInParameterValuesWithInsertColumns(Map<String, ?> args) { protected List<Object> matchInParameterValuesWithInsertColumns(Map<String, ?> args) {
return this.tableMetaDataContext.matchInParameterValuesWithInsertColumns(args); return this.tableMetaDataContext.matchInParameterValuesWithInsertColumns(args);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -47,7 +47,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
* any meta-data processing if you want to use parameter names that do not * any meta-data processing if you want to use parameter names that do not
* match what is declared during the stored procedure compilation. * match what is declared during the stored procedure compilation.
* *
* <p>The actual insert is being handled using Spring's {@link JdbcTemplate}. * <p>The actual call is being handled using Spring's {@link JdbcTemplate}.
* *
* <p>Many of the configuration methods return the current instance of the * <p>Many of the configuration methods return the current instance of the
* SimpleJdbcCall in order to provide the ability to chain multiple ones * SimpleJdbcCall in order to provide the ability to chain multiple ones

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,17 +26,17 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.KeyHolder; import org.springframework.jdbc.support.KeyHolder;
/** /**
* A SimpleJdbcInsert is a multithreaded, reusable object providing easy insert * A SimpleJdbcInsert is a multithreaded, reusable object providing easy (batch) insert
* capabilities for a table. It provides meta-data processing to simplify the code * capabilities for a table. It provides meta-data processing to simplify the code
* needed to construct a basic insert statement. All you need to provide is the * needed to construct a basic insert statement. All you need to provide is the name
* name of the table and a Map containing the column names and the column values. * of the table and a Map containing the column names and the column values.
* *
* <p>The meta-data processing is based on the DatabaseMetaData provided by the * <p>The meta-data processing is based on the DatabaseMetaData provided by the
* JDBC driver. As long as the JDBC driver can provide the names of the columns * JDBC driver. As long as the JDBC driver can provide the names of the columns
* for a specified table then we can rely on this auto-detection feature. If that * for a specified table then we can rely on this auto-detection feature. If that
* is not the case, then the column names must be specified explicitly. * is not the case, then the column names must be specified explicitly.
* *
* <p>The actual insert is handled using Spring's {@link JdbcTemplate}. * <p>The actual (batch) insert is handled using Spring's {@link JdbcTemplate}.
* *
* <p>Many of the configuration methods return the current instance of the * <p>Many of the configuration methods return the current instance of the
* SimpleJdbcInsert to provide the ability to chain multiple ones together * SimpleJdbcInsert to provide the ability to chain multiple ones together
@ -142,8 +142,8 @@ public class SimpleJdbcInsert extends AbstractJdbcInsert implements SimpleJdbcIn
return doExecuteAndReturnKeyHolder(parameterSource); return doExecuteAndReturnKeyHolder(parameterSource);
} }
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override
public int[] executeBatch(Map<String, ?>... batch) { public int[] executeBatch(Map<String, ?>... batch) {
return doExecuteBatch(batch); return doExecuteBatch(batch);
} }

View File

@ -57,15 +57,17 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* Default implementation of {@link DatabaseClient}. * The default implementation of {@link DatabaseClient},
* as created by the static factory method.
* *
* @author Mark Paluch * @author Mark Paluch
* @author Mingyuan Wu * @author Mingyuan Wu
* @author Bogdan Ilchyshyn * @author Bogdan Ilchyshyn
* @author Simon Baslé * @author Simon Baslé
* @since 5.3 * @since 5.3
* @see DatabaseClient#create(ConnectionFactory)
*/ */
class DefaultDatabaseClient implements DatabaseClient { final class DefaultDatabaseClient implements DatabaseClient {
private final Log logger = LogFactory.getLog(getClass()); private final Log logger = LogFactory.getLog(getClass());
@ -251,11 +253,12 @@ class DefaultDatabaseClient implements DatabaseClient {
"Value at index %d must not be null. Use bindNull(…) instead.", index)); "Value at index %d must not be null. Use bindNull(…) instead.", index));
Map<Integer, Parameter> byIndex = new LinkedHashMap<>(this.byIndex); Map<Integer, Parameter> byIndex = new LinkedHashMap<>(this.byIndex);
if (value instanceof Parameter p) { if (value instanceof Parameter param) {
byIndex.put(index, p); byIndex.put(index, param);
} }
else if (value instanceof org.springframework.r2dbc.core.Parameter p) { else if (value instanceof org.springframework.r2dbc.core.Parameter param) {
byIndex.put(index, p.hasValue() ? Parameters.in(p.getValue()) : Parameters.in(p.getType())); Object pv = param.getValue();
byIndex.put(index, (pv != null ? Parameters.in(pv) : Parameters.in(param.getType())));
} }
else { else {
byIndex.put(index, Parameters.in(value)); byIndex.put(index, Parameters.in(value));

View File

@ -22,7 +22,6 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
@ -380,6 +379,7 @@ abstract class NamedParameterUtils {
private final int endIndex; private final int endIndex;
ParameterHolder(String parameterName, int startIndex, int endIndex) { ParameterHolder(String parameterName, int startIndex, int endIndex) {
Assert.notNull(parameterName, "Parameter name must not be null");
this.parameterName = parameterName; this.parameterName = parameterName;
this.startIndex = startIndex; this.startIndex = startIndex;
this.endIndex = endIndex; this.endIndex = endIndex;
@ -398,20 +398,15 @@ abstract class NamedParameterUtils {
} }
@Override @Override
public boolean equals(@Nullable Object o) { public boolean equals(@Nullable Object other) {
if (this == o) { return (this == other || (other instanceof ParameterHolder that &&
return true; this.startIndex == that.startIndex && this.endIndex == that.endIndex &&
} this.parameterName.equals(that.parameterName)));
if (!(o instanceof ParameterHolder that)) {
return false;
}
return this.startIndex == that.startIndex && this.endIndex == that.endIndex
&& Objects.equals(this.parameterName, that.parameterName);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(this.parameterName, this.startIndex, this.endIndex); return this.parameterName.hashCode();
} }
} }

View File

@ -16,8 +16,6 @@
package org.springframework.r2dbc.core; package org.springframework.r2dbc.core;
import java.util.Objects;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
@ -111,20 +109,15 @@ public final class Parameter {
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object other) {
if (this == obj) { return (this == other || (other instanceof Parameter that &&
return true; ObjectUtils.nullSafeEquals(this.value, that.value) &&
} ObjectUtils.nullSafeEquals(this.type, that.type)));
if (!(obj instanceof Parameter other)) {
return false;
}
return (ObjectUtils.nullSafeEquals(this.value, other.value) &&
ObjectUtils.nullSafeEquals(this.type, other.type));
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(this.value, this.type); return ObjectUtils.nullSafeHashCode(this.value) + ObjectUtils.nullSafeHashCode(this.type);
} }
@Override @Override

View File

@ -62,14 +62,17 @@ import org.springframework.web.util.UriBuilder;
import org.springframework.web.util.UriBuilderFactory; import org.springframework.web.util.UriBuilderFactory;
/** /**
* Default implementation of {@link WebClient}. * The default implementation of {@link WebClient},
* as created by the static factory methods.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Brian Clozel * @author Brian Clozel
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 5.0 * @since 5.0
* @see WebClient#create()
* @see WebClient#create(String)
*/ */
class DefaultWebClient implements WebClient { final class DefaultWebClient implements WebClient {
private static final String URI_TEMPLATE_ATTRIBUTE = WebClient.class.getName() + ".uriTemplate"; private static final String URI_TEMPLATE_ATTRIBUTE = WebClient.class.getName() + ".uriTemplate";
@ -104,9 +107,9 @@ class DefaultWebClient implements WebClient {
private final DefaultWebClientBuilder builder; private final DefaultWebClientBuilder builder;
DefaultWebClient(ExchangeFunction exchangeFunction, @Nullable ExchangeFilterFunction filterFunctions, UriBuilderFactory uriBuilderFactory, DefaultWebClient(ExchangeFunction exchangeFunction, @Nullable ExchangeFilterFunction filterFunctions,
@Nullable HttpHeaders defaultHeaders, @Nullable MultiValueMap<String, String> defaultCookies, UriBuilderFactory uriBuilderFactory, @Nullable HttpHeaders defaultHeaders,
@Nullable Consumer<RequestHeadersSpec<?>> defaultRequest, @Nullable MultiValueMap<String, String> defaultCookies, @Nullable Consumer<RequestHeadersSpec<?>> defaultRequest,
@Nullable Map<Predicate<HttpStatusCode>, Function<ClientResponse, Mono<? extends Throwable>>> statusHandlerMap, @Nullable Map<Predicate<HttpStatusCode>, Function<ClientResponse, Mono<? extends Throwable>>> statusHandlerMap,
ObservationRegistry observationRegistry, @Nullable ClientRequestObservationConvention observationConvention, ObservationRegistry observationRegistry, @Nullable ClientRequestObservationConvention observationConvention,
DefaultWebClientBuilder builder) { DefaultWebClientBuilder builder) {
@ -215,12 +218,10 @@ class DefaultWebClient implements WebClient {
@Nullable @Nullable
private Consumer<ClientHttpRequest> httpRequestConsumer; private Consumer<ClientHttpRequest> httpRequestConsumer;
DefaultRequestBodyUriSpec(HttpMethod httpMethod) { DefaultRequestBodyUriSpec(HttpMethod httpMethod) {
this.httpMethod = httpMethod; this.httpMethod = httpMethod;
} }
@Override @Override
public RequestBodySpec uri(String uriTemplate, Object... uriVariables) { public RequestBodySpec uri(String uriTemplate, Object... uriVariables) {
attribute(URI_TEMPLATE_ATTRIBUTE, uriTemplate); attribute(URI_TEMPLATE_ATTRIBUTE, uriTemplate);
@ -338,8 +339,8 @@ class DefaultWebClient implements WebClient {
return this; return this;
} }
@Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override
public RequestBodySpec context(Function<Context, Context> contextModifier) { public RequestBodySpec context(Function<Context, Context> contextModifier) {
this.contextModifier = (this.contextModifier != null ? this.contextModifier = (this.contextModifier != null ?
this.contextModifier.andThen(contextModifier) : contextModifier); this.contextModifier.andThen(contextModifier) : contextModifier);
@ -431,8 +432,8 @@ class DefaultWebClient implements WebClient {
}); });
} }
@Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override
public Mono<ClientResponse> exchange() { public Mono<ClientResponse> exchange() {
ClientRequestObservationContext observationContext = new ClientRequestObservationContext(); ClientRequestObservationContext observationContext = new ClientRequestObservationContext();
ClientRequest.Builder requestBuilder = initRequestBuilder(); ClientRequest.Builder requestBuilder = initRequestBuilder();
@ -519,7 +520,6 @@ class DefaultWebClient implements WebClient {
private static final StatusHandler DEFAULT_STATUS_HANDLER = private static final StatusHandler DEFAULT_STATUS_HANDLER =
new StatusHandler(STATUS_CODE_ERROR, ClientResponse::createException); new StatusHandler(STATUS_CODE_ERROR, ClientResponse::createException);
private final HttpMethod httpMethod; private final HttpMethod httpMethod;
private final URI uri; private final URI uri;
@ -530,9 +530,7 @@ class DefaultWebClient implements WebClient {
private final int defaultStatusHandlerCount; private final int defaultStatusHandlerCount;
DefaultResponseSpec(HttpMethod httpMethod, URI uri, Mono<ClientResponse> responseMono,
DefaultResponseSpec(
HttpMethod httpMethod, URI uri, Mono<ClientResponse> responseMono,
List<StatusHandler> defaultStatusHandlers) { List<StatusHandler> defaultStatusHandlers) {
this.httpMethod = httpMethod; this.httpMethod = httpMethod;
@ -543,7 +541,6 @@ class DefaultWebClient implements WebClient {
this.defaultStatusHandlerCount = this.statusHandlers.size(); this.defaultStatusHandlerCount = this.statusHandlers.size();
} }
@Override @Override
public ResponseSpec onStatus(Predicate<HttpStatusCode> statusCodePredicate, public ResponseSpec onStatus(Predicate<HttpStatusCode> statusCodePredicate,
Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) { Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) {
@ -734,6 +731,7 @@ class DefaultWebClient implements WebClient {
} }
} }
private static class ObservationFilterFunction implements ExchangeFilterFunction { private static class ObservationFilterFunction implements ExchangeFilterFunction {
private final ClientRequestObservationContext observationContext; private final ClientRequestObservationContext observationContext;
@ -744,8 +742,7 @@ class DefaultWebClient implements WebClient {
@Override @Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) { public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
return next.exchange(request) return next.exchange(request).doOnNext(this.observationContext::setResponse);
.doOnNext(this.observationContext::setResponse);
} }
} }