【问题标题】:Update 1 or multiple specific field MongoDB using Spring boot WebFlux,Spring Data MongoDB Reactive and ReactiveMongoRepository使用 Spring Boot WebFlux、Spring Data MongoDB Reactive 和 ReactiveMongoRepository 更新 1 个或多个特定字段 MongoDB
【发布时间】: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" }

标签: java spring-boot spring-webflux spring-data-mongodb-reactive


【解决方案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;
            })
    

    您完全忽略获取的Taskb 实例)并使用自己的值更新task。你可能需要这样的东西:

    .map(fetchedTask -> {
           if (task.getTask() != null) {
               fetchedTask.setTask(task.getTask());
           }
            return fetchedTask;
        })
    

    【讨论】:

    • 非常感谢。我解决了。但我必须return fetchTask。如果我return Task,那是不能改变的。
    猜你喜欢
    • 1970-01-01
    • 2020-12-10
    • 2017-09-04
    • 2019-01-23
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 2021-05-03
    • 2016-01-08
    相关资源
    最近更新 更多