How can I update specific filed of my class by PUT method in SpringBoot rest api - spring

I used SpringBoot, and in the PUT method I check if the score exists then I want to update the score and also update the history by adding the latest score to it.
The Score Class:
package thesisMongoProject;
import java.util.Date;
import java.util.List;
import javax.validation.constraints.NotBlank;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import com.fasterxml.jackson.annotation.JsonView;
#Document(collection = "score")
public class Score {
#Id
#NotBlank
#JsonView(Views.class)
private String score;
#NotBlank
#JsonView(Views.class)
private String player;
#NotBlank
#JsonView(Views.class)
private String code;
#JsonView(Views.class)
private Date date;
private List<History> history;
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
public String getPlayer() {
return player;
}
public void setPlayer(String player) {
this.player = player;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<History> getHistory() {
return history;
}
public void setHistory(List<History> history) {
this.history = history;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
#Override
public String toString() {
return "Score [score=" + score + ", player=" + player + ", code=" + code + ", history=" + history + ", date="
+ date + "]";
}
}
The ScoreRepository:
package thesisMongoProject.Repository;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import thesisMongoProject.Score;
import thesisMongoProject.ScoreDto;
#Repository
public interface ScoreRepository extends MongoRepository<Score, String>{
public Score findByScore(String score);
public void save(ScoreDto scoredto, String score);
}
But the PUT method save a new instance into the MongoDB instead of updating the existing one
The PUT method:
//Update Score By ID
#PutMapping("/{score}")
public ResponseEntity<?> updatePlayerByID(
#PathVariable("score")String score,
#RequestBody #JsonView(Views.class) #Valid Score score1){
Score findscore = srepo.findByScore(score);
if(findscore == null)
return ResponseEntity.status(404).body("There is not Score!");
else {
history = new ArrayList<History>();
h = new History();
h.setScore(score1.getScore());
h.setDate(score1.getDate());
history.add(h);
score1.setHistory(history);
srepo.save(score1);
return ResponseEntity.ok(score1);
}
}
Also i tried to use ScoreDTO and #PatchMapping like this:
The ScoreDTo Class:
package thesisMongoProject;
import java.util.List;
public class ScoreDto {
private String score;
List<History> history;
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
public List<History> getHistory() {
return history;
}
public void setHistory(List<History> history) {
this.history = history;
}
}
And the PATCHMAPPING:
#PatchMapping("/{score}")
public ResponseEntity<?> updateByScore(
#PathVariable("score")String score,
#RequestBody ScoreDto score1){
Score findscore = srepo.findByScore(score);
if(findscore == null)
return ResponseEntity.status(404).body("There is not Score!");
else {
srepo.save(score1, score);
return ResponseEntity.ok(score1);
}
}
but in my console I have an error:
org.springframework.data.mapping.PropertyReferenceException: No property save found for type Score! Did you mean 'date'?
could you help me how can i update the existing field of score, please?!

The primary key of a database should not be mutable. If there are multiple players with the same score, the earlier players' data would be replaced.
Ideally, for updating an existing document where id and all its new fields are known, something like this can be done:
score1.setScore(score);
srepo.save(score1);
Assuming score is the id of the document that is to be updated and score1 contains all other fields correctly, this will replace the existing document with id score with the new one score1.
In the first code ( the PUT method ), score1 should have the same id as findscore, then it will update the existing document.
Score findscore = srepo.findByScore(score);
if(findscore == null)
return ResponseEntity.status(404).body("There is not Score!");
else {
history = new ArrayList<History>();
h = new History();
h.setScore(score1.getScore());
h.setDate(score1.getDate());
history.add(h);
Also, for the exception you are getting, this save method
public void save(ScoreDto scoredto, String score);
can't be handled by the spring data repository automatically, you will have to define its implementation. More on what kind of methods can be defined or not here. The Standard save method in the repository can be used to achieve the required.

Related

identifier of an instance of ...was altered from

i found many response about this title "identifier of an instance of ...was altered from ..." but none of this give me a solution.
i am using PostgreSQL
with just 2 column id_type and libelle.
here is my Model level :
package com.stev.pillecons.pilleCons.models;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
#Entity(name = "type_pille")
#JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class LePille {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private int id_type;
private String libelle;
public LePille(){}
public String getLibelle() {
return libelle;
}
public void setLibelle(String libelle) {
this.libelle = libelle;
}
public int getId_type() {
return id_type;
}
public void setId_type(int id_type) {
this.id_type = id_type;
}
}
My Service level :
#Override
public LePille updatePille(Integer id, LePille Sourcepille) {
Optional<LePille> existingSession = pilleRepo.findById(id);
if (existingSession.isPresent())
{
LePille Targetpile = existingSession.get();
BeanUtils.copyProperties(Sourcepille, Targetpile);
return pilleRepo.saveAndFlush(Targetpile);
}
else
{
throw new PilleException("pille not found");
}
}
when i debug it, with the data
{"id_type":10,"libelle":"dsf"}
with postman
the value of TargetPille is : {"id_type":10,"libelle":"dsf"}
and the value of SourcePille : {"id_type":0,"libelle":"popo"}
last but not least is Controller level:
#RequestMapping(value = "{id}", method = RequestMethod.PUT)
public ResponseEntity update(#PathVariable Integer id, #RequestBody LePille session) {
LePille updPille = pilleService.updatePille(id, session);
return new ResponseEntity<LePille>(updPille, HttpStatus.OK);
}
it is strange because juste update that not working, Create, Read and Delete works fine.
thanks in advance
i just change the code like this:
BeanUtils.copyProperties(Sourcepille, Targetpile, "id_type");
just add the id_type to ignore variable

How i can separate a table which have null and non null elements using spring concept

for instance, I have a table with different locations and their description too. Now I need to print the locations which have descriptions on one page or in one box and simultaneously the locations which do not have descriptions should be displayed on another page.
NOTE:
this has to be done by using spring concept only
for reference, I was able to print the locations which have no descriptions in the below fashion.
entity
package com.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
#Entity
#Table(name= "loc_dtls")
public class Location {
#Id
#GeneratedValue(strategy = jakarta.persistence.GenerationType.IDENTITY)
private long id;
#Column(name="place_name")
private String placeName;
#Column(name="place_description")
private String placeDesc;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getPlaceName() {
return placeName;
}
public void setPlaceName(String placeName) {
this.placeName = placeName;
}
public String getPlaceDesc() {
return placeDesc;
}
public void setPlaceDesc(String placeDesc) {
this.placeDesc = placeDesc;
}
#Override
public String toString() {
return "Location [id=" + id + ", placeName=" + placeName + ", placeDesc=" + placeDesc + "]";
}
}
controller
#GetMapping("/")
public String singleElement(Model m) {
List<Location> util = locRepo.findByplaceDesc(null);
m.addAttribute("unlist_places", util);
return "index";
}
repository
#Repository
public interface LocationRepository extends JpaRepository<Location, Long> {
public List<Location> findByplaceName(String placeName);
public List<Location> findByplaceDesc(String placeDesc);
}
html
<select>
<option>--select--</option>
<option th:each="p : ${unlist_places}"
th:text="${p.placeName}">
</option>
</select>
MySql Database

500 Internal Server Error; when using POST method in springBoot rest api

I used Spring Boot, POST method for create a new score for my player.
In POST method, I check if the player and game exists then create new score and also add score and its related date into the history of my score's class.
Each score has history which contains score and its date. the history has type list of History's class
The History Class:
package thesisMongoProject;
import java.util.Date;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document(collection = "history")
public class History {
#Id
private String score;
private Date date;
public History(String score, Date date) {
super();
this.score = score;
this.date = date;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
#Override
public String toString() {
return "History [score=" + score + ", date=" + date + "]";
}
}
The Score Class:
package thesisMongoProject;
import java.util.Date;
import java.util.List;
import javax.validation.constraints.NotBlank;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import com.fasterxml.jackson.annotation.JsonView;
#Document(collection = "score")
public class Score {
#Id
#NotBlank
#JsonView(Views.class)
private String score;
#NotBlank
#JsonView(Views.class)
private String player;
#NotBlank
#JsonView(Views.class)
private String code;
#JsonView(Views.class)
private Date date;
private List<History> history;
public Score(#NotBlank String score, String player, String code, List<History> history, Date date) {
super();
this.score = score;
this.player = player;
this.code = code;
this.history = history;
this.date = date;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
public String getPlayer() {
return player;
}
public void setPlayer(String player) {
this.player = player;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<History> getHistory() {
return history;
}
public void setHistory(List<History> history) {
this.history = history;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
#Override
public String toString() {
return "Score [score=" + score + ", player=" + player + ", code=" + code + ", history=" + history + ", date="
+ date + "]";
}
}
And the POST method:
#RestController
#RequestMapping("/score")
public class ScoreController {
#Autowired
private ScoreRepository srepo;
#Autowired
private PlayerRepository prepo;
#Autowired
private GamesRepository grepo;
#Autowired
private HistoryRepository hrepo;
private List<History> history;
private History h = null;
//Create Score
#PostMapping
public ResponseEntity<?> createScore(#RequestBody #JsonView(Views.class) #Valid Score score) {
//check player exist
Player p = prepo.findByNickname(score.getPlayer());
//check game's cod exist
Games g = grepo.findByCode(score.getCode());
//check score exist
Score s = srepo.findByScore(score.getScore());
// = hrepo.findByScore(score.getScore());
if(s != null)
{
return ResponseEntity.status(409).body("Conflict!!");
}else if((p != null) && (g != null)) {
h.setScore(score.getScore());
h.setDate(score.getDate());
hrepo.save(h);
history.add(h);
//history.add(hrepo.findById(score.getScore()).get());
score.setHistory(history);
srepo.save(score);
return ResponseEntity.status(201).body("Created!");
}
else {
return ResponseEntity.status(400).body("Bad Request!");
}
}
In my POST method I tried to setScore and setDate for an object of History class, and then I saved them by hrepo which is history Repository and then I added this to the history variable of type List<History>, after that I setHistory of my score class with srepo, Score repository . But when I execute my program, in PostMan I have 500 Internal Server Error and in the console I have this Error:
java.lang.NullPointerException: null
at thesisMongoProject.controller.ScoreController.createScore(ScoreController.java:63) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
which is exactly the line that I setScore of object h, h.setScore(score.getScore());
I cannot understand what is my mistake.
Initialize both, you should not get NPE after that
private List<History> history=new ArrayList<>();
private History h = new History();
field h in this line
private History h = null;
may be local variable like below.
}else if((p != null) && (g != null)) {
History h = new History(); //add local variable here.
h.setScore(score.getScore());

not able to fetch transient field from database in spring

I made a web crawler that crawls data from a website and persist data in database.Fields of database are
occasions
day
data
state
Now i added an extra field image to database and i had to set value of the images in database manually as i am not getting this field from web crawler.So i made the field image #transient in my hibernate model class
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
#Entity
#Table(name="Holidays")
public class Holidays implements Serializable {
private static final long serialVersionUID = 6705527563808382509L;
String day;
String date;
#Id
String occasion;
#Transient
String image;
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
String state;
#Override
public String toString() {
return "Holidays [day=" + day + ", date=" + date + ", occasion=" + occasion + ", state=" + state + "]";
}
public Holidays() {
super();
// TODO Auto-generated constructor stub
}
public Holidays(String day, String date, String occasion, String state) {
super();
this.day = day;
this.date = date;
this.occasion = occasion;
this.state = state;
this.image=image;
}
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getOccasion() {
return occasion;
}
public void setOccasion(String occasion) {
this.occasion = occasion;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
Now after populating the field image i wanted to fetch this field from databse but is is showing me null.Is is due to transient property?Please guide

Couchbase query exception on runtime Unsupported parameter type for key: class com.couchbase.client.protocol.views.Query

I am getting this exception every time i try to query a view on Couchbase DB from my spring boot application.
Unsupported parameter type for key: class com.couchbase.client.protocol.views.Query.
I was setting a string on setKey() method of Query class, got an exception. But then I checked the API and provided a json to setKey, still not working. Have searched a lot but could not get this to work.
I am sharing the code snippet in this post as well.
Application.properties
spring.couchbase.bucket.password=
spring.couchbase.bucket.name=default
spring.couchbase.bootstrap-hosts=127.0.0.1
spring.data.couchbase.repositories.enabled=true
PlayerRepository
public interface PlayerRepository extends CouchbaseRepository<Player, Integer>
{
#View(designDocument = "player", viewName = "all")
public List<Player> findAll();
#View(designDocument = "player", viewName = "by_Name")
public Player findByName(Query query);
#View(designDocument = "player", viewName = "by_TeamId")
public List<Player> findByTeamId(Query query);
}
Player.java
#Document
public class Player
{
#Id
int playerId;
#Field
String name;
#Field
String type;
#Field
String country;
#Field
String playingHand;
#Field
String era;
#Field
int teamId;
#Field
int odiCenturies;
#Field
int testCenturies;
public Player(){}
public Player(int playerId, String name, String type, String country, String playingHand, String era, int teamId,
int odiCenturies, int testCenturies) {
super();
this.playerId = playerId;
this.name = name;
this.type = type;
this.country = country;
this.playingHand = playingHand;
this.era = era;
this.teamId = teamId;
this.odiCenturies = odiCenturies;
this.testCenturies = testCenturies;
}
SpringBootApplication class
#SpringBootApplication
public class CricketTeamSelectionMain
{
/**
* #param args
*/
public static void main(String[] args)
{
SpringApplication.run(CricketTeamSelectionMain.class, args);
}
#Configuration
#EnableCouchbaseRepositories
public static class DBConfig extends AbstractCouchbaseConfiguration
{
#Value("${spring.couchbase.bucket.name}")
private String bucketName;
#Value("${spring.couchbase.bucket.password}")
private String password;
#Value("${spring.couchbase.bootstrap-hosts}")
private String ip;
#Override
public String getBucketName() {
return this.bucketName;
}
#Override
public String getBucketPassword() {
return this.password;
}
#Override
public List<String> getBootstrapHosts() {
return Arrays.asList(this.ip);
}
}
}
PlayerService class
package org.ups.fantasyCricket.service;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.ups.fantasyCricket.CricketTeamSelectionMain.DBConfig;
import org.ups.fantasyCricket.Model.Player;
import org.ups.fantasyCricket.Repository.PlayerRepository;
import com.couchbase.client.CouchbaseClient;
import com.couchbase.client.protocol.views.Query;
import com.couchbase.client.protocol.views.View;
import com.couchbase.client.protocol.views.ViewResponse;
#Service
public class PlayerService
{
#Autowired
PlayerRepository playerRepo;
private CouchbaseClient client;
public List<Player> getAllPlayers()
{
List<Player> allPlayerLists = new ArrayList<Player>();
/*allPlayerLists.addAll((Collection<? extends Player>) playerRepo.findAll());
return allPlayerLists;*/
playerRepo.findAll().forEach(allPlayerLists::add);
return allPlayerLists;
}
public Player getPlayerByName(String name)
{
DBConfig dbCon = new DBConfig();
try
{
Query query = new Query();
query.setIncludeDocs(true);
query.setKey(name);
Player player = playerRepo.findByName(query);
return player;
}
catch(Exception e)
{
e.printStackTrace();
System.out.println(e.getMessage());
}
return null;
}
public String addPlayer(Player player)
{
playerRepo.save(player);
return "Success";
}
public String updatePlayer(Player player, int id)
{
playerRepo.save(player);
return "Success";
}
public List<Player> getPlayersByTeamId(int teamId)
{
List<Player> allPlayerLists = new ArrayList<Player>();
Query query = new Query();
query.setKey(String.valueOf(teamId));
playerRepo.findByTeamId(query).forEach(allPlayerLists::add);
return allPlayerLists;
}
public String addPlayers(List<Player> players)
{
playerRepo.save(players);
return "Success";
}
}
View by_Name on CouchBase DB
function (doc) {
emit(doc.name, doc);
}
Which version of spring-data-couchbase are you using? Starting with 2.x, the #Query annotation uses query derivation and you cannot use a ViewQuery as a parameter anymore... Have a look at the docs, on query derivation with a view.
You could probably use the CouchbaseTemplate to perform a manual query though.

Resources