Spring Webflux - 反应式存储库 saveAll(Iterable<S>) 与 saveAll(Publisher<S>)
Spring Webflux - reactive repository saveAll(Iterable<S>) vs saveAll(Publisher<S>)
关于 webflux 反应式存储库的小问题,尤其是关于方法 saveAll Flux saveAll(Iterable var1);与 Flux saveAll(Publisher var1);
想对比一下,我写了以下内容:
@Controller
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Autowired
private SomeReactiveRepository someReactiveRepository;
@PostMapping(path = "/saveListInsideMono", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<QuestionResponse> saveListInsideMono(@RequestBody Mono<QuestionRequest> questionRequestMono) {
//just doing some business transformation on the list inside the mono
Mono<List<String>> enhancedStringListMono = questionRequestMono.map(questionRequest -> enhance(questionRequest));
//take the pojo inside the mono and map it to a saveAllAndConvertToResponse method (see next method)
Mono<QuestionResponse> questionResponseMono = enhancedStringListMono.map(enhancedStringList -> saveAllAndConvertToResponse(enhancedStringList));
return questionResponseMono;
}
private QuestionResponse saveAllAndConvertToResponse(List<String> enhancedStringList) {
// use the repository <S extends T> Flux<S> saveAll(Iterable<S> var1); + subscribe
return someReactiveRepository.saveAll(enhancedStringList).thenReturn(new QuestionResponse(enhancedStringList));
//this also works but not good to subscribe
//someReactiveRepository.saveAll(enhancedStringList).subscribe();
//return new QuestionResponse(enhancedStringList);
}
@PostMapping(path = "/saveFlux", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<QuestionResponse> saveFlux(@RequestBody Mono<QuestionRequest> questionRequestMono) {
//just doing some business transformation on the list inside the mono
Mono<List<String>> enhancedStringListMono = questionRequestMono.map(questionRequest -> enhance(questionRequest));
// use the repository <S extends T> Flux<S> saveAll(Publisher<S> var1); to save the flatMapMany + fromIterable directly
Flux<String> enhancedStringFlux = someReactiveRepository.saveAll(enhancedStringListMono.flatMapMany(Flux::fromIterable));
Mono<QuestionResponse> questionResponseMono = enhancedStringFlux.collectList().map(enhancedString -> convertToResponse(enhancedString));
return questionResponseMono;
}
private QuestionResponse convertToResponse(List<String> enhancedStringList) {
//return the object needed
return new QuestionResponse(enhancedStringList);
}
private static List<String> enhance(QuestionRequest questionRequest) {
//dummy business transformation logic
List<String> baseList = questionRequest.getList();
List<String> enhancedList = baseList.stream().map(oneString -> "enhanced" + oneString).collect(Collectors.toList());
return enhancedList;
}
public class QuestionRequest {
private List<String> list;
public List<String> getList() {
return list;
}
}
public class QuestionResponse {
private List<String> enhancedList;
public QuestionResponse(List<String> enhancedList) {
this.enhancedList = enhancedList;
}
}
}
就“正确性”而言,这两个代码都符合预期。一切都成功持久化。
但就性能、反应范式、数据库的 IO 利用率、Netty Core 使用而言,“最佳”解决方案是什么?为什么?
谢谢
这完全取决于您当前拥有的对象。如果您有 Flux
个对象,请使用采用 Publisher
的 saveAll 方法。如果您有实际的 Collection
个对象,请使用采用 Iterable
.
的 saveAll 方法
例如,如果您查看实现 SimpleReactiveCassandraRepository
,saveAll 的实现采用 Iterable
只是将其包装在 Flux 中并委托给接受 [=11] 的 saveAll 方法=]
public <S extends T> Flux<S> saveAll(Iterable<S> entities) {
Assert.notNull(entities, "The given Iterable of entities must not be null");
return saveAll(Flux.fromIterable(entities));
}
因此,在 IO 利用率或 netty 核心使用方面应该没有差异。此外,两者都遵循反应式范式。
关于 webflux 反应式存储库的小问题,尤其是关于方法 saveAll Flux saveAll(Iterable var1);与 Flux saveAll(Publisher var1);
想对比一下,我写了以下内容:
@Controller
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Autowired
private SomeReactiveRepository someReactiveRepository;
@PostMapping(path = "/saveListInsideMono", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<QuestionResponse> saveListInsideMono(@RequestBody Mono<QuestionRequest> questionRequestMono) {
//just doing some business transformation on the list inside the mono
Mono<List<String>> enhancedStringListMono = questionRequestMono.map(questionRequest -> enhance(questionRequest));
//take the pojo inside the mono and map it to a saveAllAndConvertToResponse method (see next method)
Mono<QuestionResponse> questionResponseMono = enhancedStringListMono.map(enhancedStringList -> saveAllAndConvertToResponse(enhancedStringList));
return questionResponseMono;
}
private QuestionResponse saveAllAndConvertToResponse(List<String> enhancedStringList) {
// use the repository <S extends T> Flux<S> saveAll(Iterable<S> var1); + subscribe
return someReactiveRepository.saveAll(enhancedStringList).thenReturn(new QuestionResponse(enhancedStringList));
//this also works but not good to subscribe
//someReactiveRepository.saveAll(enhancedStringList).subscribe();
//return new QuestionResponse(enhancedStringList);
}
@PostMapping(path = "/saveFlux", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<QuestionResponse> saveFlux(@RequestBody Mono<QuestionRequest> questionRequestMono) {
//just doing some business transformation on the list inside the mono
Mono<List<String>> enhancedStringListMono = questionRequestMono.map(questionRequest -> enhance(questionRequest));
// use the repository <S extends T> Flux<S> saveAll(Publisher<S> var1); to save the flatMapMany + fromIterable directly
Flux<String> enhancedStringFlux = someReactiveRepository.saveAll(enhancedStringListMono.flatMapMany(Flux::fromIterable));
Mono<QuestionResponse> questionResponseMono = enhancedStringFlux.collectList().map(enhancedString -> convertToResponse(enhancedString));
return questionResponseMono;
}
private QuestionResponse convertToResponse(List<String> enhancedStringList) {
//return the object needed
return new QuestionResponse(enhancedStringList);
}
private static List<String> enhance(QuestionRequest questionRequest) {
//dummy business transformation logic
List<String> baseList = questionRequest.getList();
List<String> enhancedList = baseList.stream().map(oneString -> "enhanced" + oneString).collect(Collectors.toList());
return enhancedList;
}
public class QuestionRequest {
private List<String> list;
public List<String> getList() {
return list;
}
}
public class QuestionResponse {
private List<String> enhancedList;
public QuestionResponse(List<String> enhancedList) {
this.enhancedList = enhancedList;
}
}
}
就“正确性”而言,这两个代码都符合预期。一切都成功持久化。
但就性能、反应范式、数据库的 IO 利用率、Netty Core 使用而言,“最佳”解决方案是什么?为什么?
谢谢
这完全取决于您当前拥有的对象。如果您有 Flux
个对象,请使用采用 Publisher
的 saveAll 方法。如果您有实际的 Collection
个对象,请使用采用 Iterable
.
例如,如果您查看实现 SimpleReactiveCassandraRepository
,saveAll 的实现采用 Iterable
只是将其包装在 Flux 中并委托给接受 [=11] 的 saveAll 方法=]
public <S extends T> Flux<S> saveAll(Iterable<S> entities) {
Assert.notNull(entities, "The given Iterable of entities must not be null");
return saveAll(Flux.fromIterable(entities));
}
因此,在 IO 利用率或 netty 核心使用方面应该没有差异。此外,两者都遵循反应式范式。