2

I have the following Java POJO in my spring boot application:

    public class Round {

        private ObjectId _id;

        @NotEmpty
        @Getter
        @Setter
        @Accessors(fluent = true)
        @JsonProperty("userId")
        private String userId;

        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
        @JsonDeserialize(using = LocalDateDeserializer.class)
        @JsonSerialize(using = LocalDateSerializer.class)
        @Getter
        @Setter
        @Accessors(fluent = true)
        @JsonProperty("date")
        private LocalDate date;

        @Min(value = 1, message = "Score should not be less than 1")
        @Getter
        @Setter
        @Accessors(fluent = true)
        @JsonProperty("score")
        private int score;

        // rest of fields

}

I have the following MongoRepository:

@Repository
public interface RoundRepository extends MongoRepository<Round, String> {

    List<Round> findByUserId(String userId);

    @Query("{'userId' : ?0 , '_id' : ?1}")
    Optional<Round> findByUserIdAnd_id(String userId, ObjectId _id);

}

In my Service class I have a working create() and I am trying to implement an update() method to be used with the PUT mapping in my controller:

public Round create(String userId, @Valid @NotNull @RequestBody Round round) {

    // set userId from path
    round.userId(userId);

    roundRepository.save(round);
    return round;
}

public void put(String userId, ObjectId objectId, Round updatedRound) {

    // get original round
    Optional<Round> round = roundRepository.findByUserIdAnd_id(userId, objectId);

    //todo - how to implement PUT in mongo to update to "updatedRound"?

}

I am relatively new to MongoDB, is there a set way to do this? I.e. keep the same ObjectId etc but update other fields in the document?

java12399900
  • 1,485
  • 7
  • 26
  • 56

2 Answers2

8

Note : The following code is not tested, but it gives you an idea well. There are two scenarios.

  1. If you don't send the id with your request, the data will be inserted.
  2. If you send the existing id with your request, the data will be updated.

Annotate @Id private ObjectId _id; in your entity class

Controller

@RestController
@RequestMapping("YOUR_URL")
public class RoundController{

    @PostMapping("YOUR_URL")
    public ResponseEntity<Round> update(@Valid @RequestBody Round updateRound, BindingResult result){

        //Bindning Error handle
         if (bindingResult.hasErrors()) {
            List<String> errors = new ArrayList<>();
            for (ObjectError res : bindingResult.getFieldErrors()) {
                errors.add(res.getDefaultMessage());
            }

            throw new RuntimeError(errors.toString());
        }
        return new ResponseEntity<>(roundService.save(updateRound), HttpStatus.OK);
    }
}

Repository

interface RoundRepository extends MongoRepository<Round, ObjectId> {
}

Service

interface RoundService {
    Round save(Round round);
}

Service Implementation

@Service
public RoundServiceImpl implements RoundService{
    @Autowired
    RoundRepository repository;

    @Override
    public Round save(Round round){
        repository.save(round);
    }
}

You don't need to actually perform a special query. But if you need to do some logic.

@Override
public Round save(Round round){

    if(round.get_id()!=null){
        //update logic
    }else {
        // insert logic
    }

    repository.save(round);
}
varman
  • 8,704
  • 5
  • 19
  • 53
1

You could use the annotations @Query and @Update together.

The @Query uses de find part and @Update uses de $set part.

Example

public interface RoundRepository extends MongoRepository<Round, String> {

    @Query("{'userId' : ?0")
    @Update("{'$set': {'round': ?1}}")
    Integer updateRound(String id, Round updatedRound);
}

reference: https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongodb.repositories.queries.update

Manhattan
  • 51
  • 4