我正在学习反应式 Java,我正在尝试从数据库中执行删除操作。我使用的数据库是嵌入式 Mongo DB。
我尝试了很少的方法来从数据库中删除具有给定 ID 的电影,其中一些有效,其余的无效。想知道我是否缺少反应式编程的一些基本概念。
示例 1:删除工程
return moviesInfoService.deleteMovieInfoById(id)
.then(Mono.just(ResponseEntity.noContent().build()));
例子2:删除不起作用
moviesInfoService.deleteMovieInfoById(id);
return Mono.just(ResponseEntity.noContent().build());
示例3:删除不起作用
Mono<Void> result = moviesInfoService.deleteMovieInfoById(id);
Mono<ResponseEntity> result2 = result.map(m -> ResponseEntity.noContent().build());
return result2
示例 4:删除工作
return moviesInfoService
.getMovieInfoById(id)
.flatMap(fm -> moviesInfoService.deleteMovieInfoById(fm.getMovieInfoId()))
.then(Mono.just(ResponseEntity.noContent().build()));
我无法理解为什么在某些情况下删除有效而在某些情况下无效。请帮助我。
为什么它不起作用是因为你打破了链条,而且你还没有读过操作员的实际操作。
return moviesInfoService.deleteMovieInfoById(id)
.then(Mono.just(ResponseEntity.noContent().build()));
此处
deleteMovieInfoById
返回一个值,然后您调用 then
运算符,它将(当较早的函数完成时)丢弃该值,而是返回 ResponseEntity.noContent().build()
.
您可以只写
.then(ServerResponse.noContent().build())
,因为 ServerResponse
会给您一个 Mono
,或者如果您坚持要返回一个 ResponseEntity
,您可以改用 thenReturn(ResponseEntity.noContent().build())
,它将为您包裹在一个 Mono
中自动。
ResponseEntity
来自 http
包,这意味着它更通用,而 ServerResponse
来自 reactive
包,所以它更方便。
第二个不起作用,因为如果我们重写它更爆炸我们得到:
Mono<Void> someThing = moviesInfoService.deleteMovieInfoById(id);
Mono<ResponseEntity> response = Mono.just(ResponseEntity.noContent().build());
return response;
正如您在这里看到的,您有两个
Mono's
而其中一个(最上面的一个)未使用。在 reactor 入门中解释说 reactor 就像传送带一样工作。有两个阶段,assembly
阶段和subscription
阶段。你可以阅读它在这里.
这实际上意味着你不能让任何 mono/flux 悬空,你总是需要链接到最后一个运算符,以便反应式 java 可以对先前的函数结果做出反应。
你所谓的打破了链条.
你需要链接到
someThing
。在这里,我用then
来做。
Mono<Void> someThing = moviesInfoService.deleteMovieInfoById(id);
Mono<ResponseEntity> response = someThing.then(ServerResponse.noContent().build());
return response;
你的例子 3 有点难以发现,这是因为你隐含地理解你不能映射
Void
.
Mono<Void> result = moviesInfoService.deleteMovieInfoById(id);
Mono<ResponseEntity> result2 = result.map(m -> ResponseEntity.noContent().build());
return result2
在您的示例中,
m
是什么?返回Mono<Void
之前的功能所以m
会是什么?如果你之前的函数没有返回任何东西,那就是这样,它不会在之后运行map
函数。
所以基本上
map
不是在这里使用的运算符then
或者thenReturn
是应该使用的。
最后一个例子有效,是最惯用的解决方案。
return moviesInfoService
.getMovieInfoById(id)
.flatMap(fm -> moviesInfoService.deleteMovieInfoById(fm.getMovieInfoId()))
.then(Mono.just(ResponseEntity.noContent().build()));
然后我们可以将其重写为更详细的内容:
void Mono<ServerResponse> deleteMovie() {
final MovieService movieService = new MovieService();
return movieService.get("Terminator").flatMap(name -> {
System.out.println("calling delete on: " + name);
return movieService.delete(name);
})
.then(ServerResponse.noContent().build())
}
static class MovieService {
public Mono<String> get(String s) {
System.out.println("fetching " + s);
return Mono.just(s);
}
public Mono<Void> delete(String s) {
System.out.println("deleting " + s);
return Mono.empty();
}
}
如果你这样看
flatMap
获取什么,这是允许的,因为我们有一些我们可以 flatMap
on.delete
中调用 flatMap
并且因为我们正在返回一个 Mono<Void>
它基本上只是告诉反应链我们已经完成并且没有返回任何内容then
,我们返回ServerResponse
。你总是必须坚持你做的最后一件事。
其中大部分内容在反应式文档的反应式编程入门部分中进行了解释,并且您正在投票,因为它在 Stack Overflow 上已经回答了很多次。