使用 Spring Boot WebFlux、Spring Data MongoDB Reactive 和 ReactiveMongoRepository 更新 1 个或多个特定字段 MongoDB
Posted
技术标签:
【中文标题】使用 Spring Boot WebFlux、Spring Data MongoDB Reactive 和 ReactiveMongoRepository 更新 1 个或多个特定字段 MongoDB【英文标题】:Update 1 or multiple specific field MongoDB using Spring boot WebFlux,Spring Data MongoDB Reactive and ReactiveMongoRepository 【发布时间】:2022-01-14 02:16:59 【问题描述】:我是 java 新手。我试图为我的 API 实现更新方法。我想更新我的数据的某些字段。 这是我的数据类:
public class Task implements Serializable
@Id
private String id;
private String task;
private Boolean isCompleted;
private String userId;
我的服务接口:
public interface TaskService
void create(Task task);
Mono<Task> findById(String id);
Flux<Task> findAll();
Mono<Task> update(String Id, Task task);
Mono<Void> delete(String id);
并为服务实施:
@Service
public class TaskServiceImpl implements TaskService
@Autowired
TaskRepository taskRepository;
public void create(Task task)
taskRepository.save(task).subscribe();
public Mono<Task> findById(String Id)
return taskRepository.findById(Id);
public Flux<Task> findAll()
return taskRepository.findAll();
public Mono<Task> update(String Id, Task task)
// System.out.println(taskRepository.findById(Id));
return taskRepository.findById(Id)
.switchIfEmpty(Mono.error(new Exception("TASK_NOT_FOUND")))
.map(b ->
task.setId(Id);
if (task.getTask() != null) task.setTask(task.getTask());
if (task.getIsCompleted() != null) task.setIsCompleted(task.getIsCompleted());
if (task.getUserId() != null) task.setUserId(task.getUserId());
return task;
)
.flatMap(taskRepository::save);
public Mono<Void> delete(String id)
return taskRepository.deleteById(id);
我的控制器:
@RestController
public class TaskController
@Autowired
private TaskService taskService;
@PostMapping("/tasks")
@ResponseStatus(HttpStatus.CREATED)
public void create(@RequestBody Task task)
taskService.create(task);
@GetMapping("/tasks/id")
public ResponseEntity<Mono<Task>> findbyId(@PathVariable("id") String Id)
Mono<Task> task = taskService.findById(Id);
return new ResponseEntity<Mono<Task>>(task, task != null ? HttpStatus.OK : HttpStatus.NOT_FOUND);
@GetMapping(value = "/tasks")
@ResponseBody
public Flux<Task> findAll()
return taskService.findAll();
@PutMapping("/tasks/id")
@ResponseStatus(HttpStatus.OK)
public Mono<Task> update(@PathVariable("id") String Id, @RequestBody Task task)
return taskService.update(Id, task);
@DeleteMapping("/tasks/id")
@ResponseStatus(HttpStatus.OK)
public void delete(@PathVariable("id") String id)
taskService.delete(id).subscribe();
和任务存储库:
@Repository
public interface TaskRepository extends ReactiveMongoRepository<Task, String>
我在数据库中的数据:
"id": "2",
"task": "do",
"isCompleted": true,
"userId": "1"
我的请求正文:
"userId": "2",
"task": "updated"
我预计:
"id": "2",
"task": "updated",
"isCompleted": true,
"userId": "2"
但它回应了:
"id": "2",
"task": "updated",
"isCompleted": null,
"userId": "2"
它用空值更新我在请求中的缺失值。 如何更新数据中的特定值?
【问题讨论】:
奇怪的是你从数据库中检索但isCompleted字段在数据库中为空。 如果使用findById查询isComplete字段的值是多少可以调试? 如果我不发送除 ID 之外的请求正文,则所有值都为空。所以我认为它是用请求数据更新我的数据库,但是当我的请求数据丢失值时,它将为空。像这样:我的请求正文 "userId": "100"
然后我的数据: "id": "2", "task": null, "isCompleted": null, "userId": "100"
【参考方案1】:
在@Ikatiforis 之后,我已经解决了我的问题。
这是我的解决方案:
public Mono<Task> update(String Id, Task task)
return taskRepository.findById(Id)
.switchIfEmpty(Mono.error(new Exception("TASK_NOT_FOUND")))
.map(fetchedTask ->
task.setId(Id);
if (task.getTask() != null
fetchedTask.setTask(task.getTask());
if (task.getIsCompleted() != null)
fetchedTask.setIsCompleted(task.getIsCompleted());
if (task.getUserId() != null)
fetchedTask.setUserId(task.getUserId());
return fetchedTask;
)
.flatMap(taskRepository::save);
【讨论】:
【参考方案2】:问题出在这里:
return taskRepository.findById(Id)
.switchIfEmpty(Mono.error(new Exception("TASK_NOT_FOUND")))
.map(b ->
task.setId(Id);
if (task.getTask() != null) task.setTask(task.getTask());
if (task.getIsCompleted() != null) task.setIsCompleted(task.getIsCompleted());
if (task.getUserId() != null) task.setUserId(task.getUserId());
return task;
)
您完全忽略获取的Task
(b
实例)并使用自己的值更新task
。你可能需要这样的东西:
.map(fetchedTask ->
if (task.getTask() != null)
fetchedTask.setTask(task.getTask());
return fetchedTask;
)
【讨论】:
非常感谢。我解决了。但我必须return fetchTask
。如果我return Task
,那是不能改变的。以上是关于使用 Spring Boot WebFlux、Spring Data MongoDB Reactive 和 ReactiveMongoRepository 更新 1 个或多个特定字段 MongoDB的主要内容,如果未能解决你的问题,请参考以下文章
使用 Spring boot + WebFlux 进行全局错误处理
Spring Boot Webflux/Netty - 检测关闭的连接
spring-boot-starter-web 和 spring-boot-starter-webflux 不能一起工作吗?
如何使用 Spring Boot 对 WebFlux 进行异常处理?