|
|
|
|
@ -15,12 +15,15 @@
@@ -15,12 +15,15 @@
|
|
|
|
|
*/ |
|
|
|
|
package org.springframework.data.r2dbc.repository.query; |
|
|
|
|
|
|
|
|
|
import org.reactivestreams.Publisher; |
|
|
|
|
import reactor.core.publisher.Flux; |
|
|
|
|
import reactor.core.publisher.Mono; |
|
|
|
|
import reactor.core.publisher.MonoProcessor; |
|
|
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.Optional; |
|
|
|
|
import java.util.concurrent.ConcurrentHashMap; |
|
|
|
|
|
|
|
|
|
import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor; |
|
|
|
|
import org.springframework.data.repository.util.ReactiveWrapperConverters; |
|
|
|
|
@ -31,11 +34,12 @@ import org.springframework.data.repository.util.ReactiveWrappers;
@@ -31,11 +34,12 @@ import org.springframework.data.repository.util.ReactiveWrappers;
|
|
|
|
|
* to reactive parameter wrapper types upon creation. This class performs synchronization when accessing parameters. |
|
|
|
|
* |
|
|
|
|
* @author Mark Paluch |
|
|
|
|
* @author Christoph Strobl |
|
|
|
|
*/ |
|
|
|
|
class R2dbcParameterAccessor extends RelationalParametersParameterAccessor { |
|
|
|
|
|
|
|
|
|
private final Object[] values; |
|
|
|
|
private final List<MonoProcessor<?>> subscriptions; |
|
|
|
|
private final R2dbcQueryMethod method; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Creates a new {@link R2dbcParameterAccessor}. |
|
|
|
|
@ -45,37 +49,7 @@ class R2dbcParameterAccessor extends RelationalParametersParameterAccessor {
@@ -45,37 +49,7 @@ class R2dbcParameterAccessor extends RelationalParametersParameterAccessor {
|
|
|
|
|
super(method, values); |
|
|
|
|
|
|
|
|
|
this.values = values; |
|
|
|
|
this.subscriptions = new ArrayList<>(values.length); |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < values.length; i++) { |
|
|
|
|
|
|
|
|
|
Object value = values[i]; |
|
|
|
|
|
|
|
|
|
if (value == null || !ReactiveWrappers.supports(value.getClass())) { |
|
|
|
|
subscriptions.add(null); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ReactiveWrappers.isSingleValueType(value.getClass())) { |
|
|
|
|
subscriptions.add(ReactiveWrapperConverters.toWrapper(value, Mono.class).toProcessor()); |
|
|
|
|
} else { |
|
|
|
|
subscriptions.add(ReactiveWrapperConverters.toWrapper(value, Flux.class).collectList().toProcessor()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* (non-Javadoc) |
|
|
|
|
* @see org.springframework.data.repository.query.ParametersParameterAccessor#getValue(int) |
|
|
|
|
*/ |
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
@Override |
|
|
|
|
protected <T> T getValue(int index) { |
|
|
|
|
|
|
|
|
|
if (subscriptions.get(index) != null) { |
|
|
|
|
return (T) subscriptions.get(index).block(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return super.getValue(index); |
|
|
|
|
this.method = method; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* (non-Javadoc) |
|
|
|
|
@ -97,4 +71,61 @@ class R2dbcParameterAccessor extends RelationalParametersParameterAccessor {
@@ -97,4 +71,61 @@ class R2dbcParameterAccessor extends RelationalParametersParameterAccessor {
|
|
|
|
|
public Object getBindableValue(int index) { |
|
|
|
|
return getValue(getParameters().getBindableParameter(index).getIndex()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Resolve parameters that were provided through reactive wrapper types. Flux is collected into a list, values from |
|
|
|
|
* Mono's are used directly. |
|
|
|
|
* |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
public Mono<R2dbcParameterAccessor> resolveParameters() { |
|
|
|
|
|
|
|
|
|
boolean hasReactiveWrapper = false; |
|
|
|
|
|
|
|
|
|
for (Object value : values) { |
|
|
|
|
if (value == null || !ReactiveWrappers.supports(value.getClass())) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
hasReactiveWrapper = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!hasReactiveWrapper) { |
|
|
|
|
return Mono.just(this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Object[] resolved = new Object[values.length]; |
|
|
|
|
Map<Integer, Optional<?>> holder = new ConcurrentHashMap<>(); |
|
|
|
|
List<Publisher<?>> publishers = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < values.length; i++) { |
|
|
|
|
|
|
|
|
|
Object value = resolved[i] = values[i]; |
|
|
|
|
if (value == null || !ReactiveWrappers.supports(value.getClass())) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ReactiveWrappers.isSingleValueType(value.getClass())) { |
|
|
|
|
|
|
|
|
|
int index = i; |
|
|
|
|
publishers.add(ReactiveWrapperConverters.toWrapper(value, Mono.class) //
|
|
|
|
|
.map(Optional::of) //
|
|
|
|
|
.defaultIfEmpty(Optional.empty()) //
|
|
|
|
|
.doOnNext(it -> holder.put(index, (Optional<?>) it))); |
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
int index = i; |
|
|
|
|
publishers.add(ReactiveWrapperConverters.toWrapper(value, Flux.class) //
|
|
|
|
|
.collectList() //
|
|
|
|
|
.doOnNext(it -> holder.put(index, Optional.of(it)))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return Flux.merge(publishers).then().thenReturn(resolved).map(values -> { |
|
|
|
|
holder.forEach((index, v) -> values[index] = v.orElse(null)); |
|
|
|
|
return new R2dbcParameterAccessor(method, values); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|