I want to create a Post method to update a single property from my API main Object:
@Builder
@Document(collection = "tableItems")
@NoArgsConstructor
@AllArgsConstructor
@Data
public class TableItem {
@Id
private String id;
private int roundNumber;
private RoundState roundState;
private int bigBlind;
private int smallBlind;
private int maxSize;
private int freeSeats;
private double tableChips;
private List<Card> tableCards;
private List<Player> players;
private List<Seat> seats;
}
So, this object ist save on my MongoDB. I want to add a new Player on players, but all other properties should not change!
In my GameController, I have a @RequestMapping("/api/tableitems") and my method looks like this:
@PostMapping("/{id}/players")
public void postNewPlayer(@RequestBody Player newPlayer, String tableId) {
gameService.addNewPlayer(id, newPlayer);
}
In my GameService my addNewPlayer method looks like this:
public void addNewPlayer(Player newPlayer, String tableId) {
TableItem tableToBeUpdated = tableItemsRepo.findById(tableId)
.orElseThrow( () -> new NoSuchElementException(("Table with ID " tableId " not found!")));
tableItemsRepo.save(newPlayer);
}
IntelliJ grumbles and throws the following error message:
Inferred type 'S' for type parameter 'S' is not within its bound; should extend 'backend.model.TableItem'
And finally my repository looks like this:
@Repository
public interface TableItemsRepository extends MongoRepository<TableItem, String> {
}
Is it at all possible to update a single property of an object with @POST? How does it work? If not, how else can it be done? I am at a loss and would be very grateful for some help... Thanks a lot!
CodePudding user response:
you can have 2 solutions:
- to use a DTO (Data Transfer Object). Get a DTO in controller, create a mapper from DTO to Entity and from Entity to DTO and create a function to update the Entity from the DTO. You can see more here: https://mapstruct.org/documentation/stable/reference/html/#updating-bean-instances
- second solution, that I think that is easier to implement, it's to create a function that copy the properties of a entity to another and exclude the null ones. You can get more info here: How to ignore null values using springframework BeanUtils copyProperties?
CodePudding user response:
Thanks for the quick feedback! I have seen some thinking errors already... my Repository expects TableItems and I just give it the property I want to change(Player in Players). I also forgot by the @Post the PathVariable with the TableId.
Through your tips I have now found a solution that also works! Here my code:
Controller:
@PostMapping("/{id}/players")
public void postNewPlayer(@RequestBody Player newPlayer, @PathVariable String id) {
gameService.addNewPlayer(newPlayer, id);
}
Service:
public void addNewPlayer(Player newPlayer, String tableId) {
TableItem tableToBeUpdated = tableItemsRepo.findById(tableId)
.orElseThrow( () -> new NoSuchElementException(("Table with ID " tableId " not found!")));
List<Player> players = tableToBeUpdated.getPlayers();
if( players == null) {
players = new ArrayList<>();
tableToBeUpdated.setPlayers(players);
}
players.add(newPlayer);
tableItemsRepo.save(tableToBeUpdated);
}
I did not have to change anything in the repo. The result it looks like this in the DB:
{
"roundNumber": 2,
"bigBlind": 20,
"smallBlind": 10,
"maxSize": 2,
"freeSeats": 2,
"tableChips": 0,
"tableCards": [
{
"rank": "FIVE",
"suit": "HEARTS"
},
{
"rank": "SEVEN",
"suit": "SPADES"
}
],
"players": [
{
"playerName": "brasuca",
"playerChips": 1000,
"playerCards": [
{
"rank": "SEVEN",
"suit": "HEARTS"
},
{
"rank": "KING",
"suit": "HEARTS"
}
]
}
]}
Thank you very much for your help!!