#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); }