Обновите 1 или несколько конкретных полей MongoDB с помощью Spring boot WebFlux,Spring Data MongoDB Reactive и ReactiveMongoRepository

#java #spring-boot #spring-webflux #spring-data-mongodb-reactive

#Ява #пружинный ботинок #пружинный вебфлюкс #весна-данные-mongodb-реактивный

Вопрос:

Я новичок в 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);   Monolt;Taskgt; findById(String id);   Fluxlt;Taskgt; findAll();   Monolt;Taskgt; update(String Id, Task task);   Monolt;Voidgt; delete(String id); }  

И внедрять для услуг:

 @Service public class TaskServiceImpl implements TaskService {   @Autowired  TaskRepository taskRepository;   public void create(Task task) {  taskRepository.save(task).subscribe();  }   public Monolt;Taskgt; findById(String Id) {  return taskRepository.findById(Id);  }   public Fluxlt;Taskgt; findAll() {  return taskRepository.findAll();  }   public Monolt;Taskgt; 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 -gt; {  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 Monolt;Voidgt; 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 ResponseEntitylt;Monolt;Taskgt;gt; findbyId(@PathVariable("id") String Id) {  Monolt;Taskgt; task = taskService.findById(Id);  return new ResponseEntitylt;Monolt;Taskgt;gt;(task, task != null ? HttpStatus.OK : HttpStatus.NOT_FOUND);  }   @GetMapping(value = "/tasks")  @ResponseBody  public Fluxlt;Taskgt; findAll() {  return taskService.findAll();  }   @PutMapping("/tasks/{id}")  @ResponseStatus(HttpStatus.OK)  public Monolt;Taskgt; 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 ReactiveMongoRepositorylt;Task, Stringgt; { }  

Мои данные в БД:

 {  "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" }  

Он обновляет мое отсутствующее значение в запросе на нулевое значение. Как я могу обновить определенные значения в данных?

Комментарии:

1. Странно, что вы извлекаете данные из базы данных, но поле IsCompleted в базе данных равно нулю.

2. Вы можете отладить его, если используете запрос findById, каково значение поля IsComplete?

3. Это значение равно нулю для всех значений, если я не отправлю тело запроса, кроме идентификатора. Поэтому я думаю, что это обновление моей базы данных данными запроса, но когда мои данные запроса будут пропущены, значение будет равно нулю. Вот так: Мое тело запроса { "userId": "100"} , а затем мои данные: { "id": "2", "task": null, "isCompleted": null, "userId": "100" }

Ответ №1:

Проблема в том, что здесь:

 return taskRepository.findById(Id)  .switchIfEmpty(Mono.error(new Exception("TASK_NOT_FOUND")))  .map(b -gt; {  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 -gt; {  if (task.getTask() != null) {  fetchedTask.setTask(task.getTask());  }  return fetchedTask;  })  

Комментарии:

1. Большое вам спасибо. Я решил эту проблему. Но я должен return fetchTask . Если я return Task , то это не может измениться.

Ответ №2:

Перейдя на @Ikatiforis, я решил свою проблему.

Вот мое решение:

 public Monolt;Taskgt; update(String Id, Task task) {  return taskRepository.findById(Id)  .switchIfEmpty(Mono.error(new Exception("TASK_NOT_FOUND")))  .map(fetchedTask -gt; {  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);  }