So I'm learning Spring Boot for my uni project and I want to add values to a table that has a foreign key when the FK already exists in the other table. Im new to this stuff and I don'g really know what to do with the error that Spring gives me.
My entity
package com.example.Projekt21.entity;
import javax.persistence.*;
@Table
@Entity
public class Oscar {
@Id
@GeneratedValue
private Long id;
private Long rok;
@OneToOne
@JoinColumn(name = "idFilmu", referencedColumnName = "id")
private Film idFilmu;
@ManyToOne
@JoinColumn(name = "idRezyserea", referencedColumnName = "id")
private Rezyser idRezysera;
public Oscar(Long idOscary, Long rok) {
this.id = idOscary;
this.rok = rok;
}
public Oscar() {
}
public Long getIdOscar() {
return id;
}
public void setIdOscar(Long idOscary) {
this.id = id;
}
public Long getRok() {
return rok;
}
public void setRok(Long rok) {
this.rok = rok;
}
public Film getIdFilmu() {
return idFilmu;
}
public void setIdFilmu(Film idFilmu) {
this.idFilmu = idFilmu;
}
}
Controller
package com.example.Projekt21.controller;
import com.example.Projekt21.entity.Oscar;
import com.example.Projekt21.service.OscarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping
public class OscarController {
private final OscarService oscarService;
@Autowired
public OscarController(OscarService oscarService){
this.oscarService = oscarService;
}
@GetMapping(path = "/oscar/get")
public List<Oscar> getOscar(){
return oscarService.getOscar();
}
@PostMapping(path = "/oscar/post")
public void registerNewOscar(@RequestBody Oscar oscar){
oscarService.addNewOscar(oscar);
}
@DeleteMapping(path = "/oscar/delete/{oscarId}")
public void deleteOscar(@PathVariable("oscarId")Long oscarId){
oscarService.deleteOscar(oscarId);
}
@PutMapping(path = "/oscar/put/{oscarId}")
public void updateStudent(
@PathVariable("oscarId") Long oscarId,
@RequestParam(required = false) Long rok) {
oscarService.updateOscar(oscarId, rok);
}
}
Service
package com.example.Projekt21.service;
import com.example.Projekt21.entity.Oscar;
import com.example.Projekt21.repository.OscarRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
import java.util.Objects;
@Service
public class OscarService {
private final OscarRepository oscarRepository;
@Autowired
public OscarService(OscarRepository oscarRepository){
this.oscarRepository = oscarRepository;
}
public List<Oscar> getOscar(){
return oscarRepository.findAll();
}
public void addNewOscar(Oscar oscar){
oscarRepository.save(oscar);
}
public void deleteOscar(Long oscarId){
boolean exists = oscarRepository.existsById(oscarId);
if(!exists){
throw new IllegalStateException("Oscar o numerze id: " oscarId " nie istenieje");
}
oscarRepository.deleteById(oscarId);
}
@Transactional
public void updateOscar(Long oscarId, Long rok) {
Oscar oscar = oscarRepository.findById(oscarId).orElseThrow(() -> new IllegalStateException(
"Oscar o numerze id: " oscarId " nie istnieje"));
if (rok != null && rok > 0 && rok != oscar.getRok()) {
oscar.setRok(rok);
}
}
}
My request
{
"rok": "2020",
"idFilmu": "1",
"idRezysera": "2"
}
Error Message
JSON parse error: Cannot construct instance of `com.example.Projekt21.entity.Film` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('1');
Can someone please give me a simple explanation on how to fix my problem? Thanks
EDIT: Film entity
package com.example.Projekt21.entity;
import javax.persistence.*;
@Table
@Entity
public class Film {
@Id
@GeneratedValue
private Long id;
private String tytul;
private String gatunek;
private Long rok_produkcji;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
private Rezyser rezyser;
public Film(String tytul, String gatunek, Long rok_produkcji, Rezyser
rezyser) {
this.tytul = tytul;
this.gatunek = gatunek;
this.rok_produkcji = rok_produkcji;
this.rezyser = rezyser;
}
public Film() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTytul() {
return tytul;
}
public void setTytul(String tytul) {
this.tytul = tytul;
}
public String getGatunek() {
return gatunek;
}
public void setGatunek(String gatunek) {
this.gatunek = gatunek;
}
public Long getRok_produkcji() {
return rok_produkcji;
}
public void setRok_produkcji(Long rok_produkcji) {
this.rok_produkcji = rok_produkcji;
}
public Rezyser getRezyser() {
return rezyser;
}
public void setRezyser(Rezyser rezyser) {
this.rezyser = rezyser;
}
@Override
public String toString() {
return "Film{"
"id=" id
", tytul='" tytul '\''
", gatunek='" gatunek '\''
", rok_produkcji=" rok_produkcji
", id_rezysera=" rezyser
'}';
}
}
and Rezyser
public class Rezyser {
@Id
@GeneratedValue
private Long id;
private String imie;
private String nazwisko;
private Date data_urodzenia;
private String kraj_pochodzenia;
@OnDelete(action = OnDeleteAction.CASCADE)
@OneToMany(mappedBy = "rezyser")
private List<Film> filmList;
public Rezyser(String imie, String nazwisko, Date data_urodzenia, String
kraj_pochodzenia) {
this.imie = imie;
this.nazwisko = nazwisko;
this.data_urodzenia = data_urodzenia;
this.kraj_pochodzenia = kraj_pochodzenia;
}
//getters, setters, toString and creators
}
EDIT 2
sharing my project: https://github.com/TheFandorn/Projekt2.1
CodePudding user response:
Okey, so if anyone in the future has a similar problem this is the solution:
Controller
@PostMapping(path = "/oscar/post/{filmId}")
public Oscar addOscarToFilm(@PathVariable Long filmId, @RequestBody OscarDto
oscar){
return oscarService.addOscarToFilm(filmId, oscar);
}
Service
public Oscar addOscarToFilm(Long filmId, OscarDto oscarDto) {
if (filmId == null) {
throw new IllegalArgumentException("Id of Film you want to find is
null");
}
var film = filmRepository.findById(filmId)
.orElseThrow(() -> new IllegalArgumentException("Cannot find film
with this id: " filmId));
var filmRezyser = film.getRezyser();
var oscar = oscarDto.toOscar();
oscar.setFilm(film);
oscar.setRezyser(filmRezyser);
return oscarRepository.save(oscar);
}
dto
package com.example.Projekt21.dto;
import com.example.Projekt21.entity.Oscar;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class OscarDto {
Long rok;
public Oscar toOscar() {
return Oscar
.builder()
.rok(rok)
.build();
}
}
CodePudding user response:
It is great! We can use new class for request body, for example:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AddNewOscarRequest {
private Long oscarId;
private Long rok;
private Long filmId;
private Long rezyseraId;
}
then:
@PostMapping(path = "/oscar/create")
public Oscar addOscarToFilm(@RequestBody AddNewOscarRequest request){
return oscarService.addOscarToFilm(request);
}
If you not found entity application throws EntityNotFoundException
filmRepository.findById(filmId)
For mapping you can use new class like "OscarMapper"