【问题标题】:Spring Data JPA OneTo Many POST mapping ProblemSpring Data JPA 一对多 POST 映射问题
【发布时间】:2020-11-30 17:28:38
【问题描述】:

我正在尝试为视频库开发 REST API。 使用电影控制器,我想获取、发布、放置和删除电影实体 (其中有列 id(生成的类型标识,它是主键)、title、genre、rate 和 number in stock)

“流派”是另一个实体,事实上,一部电影可以是一个唯一的流派(在我的项目中)

我希望我的 api 接受以下 JSON 请求

{
  "title":"John Wick",
  "rate":8.2,
  "numberInStock":19,
  "genreId":2
}

所以genreId指的是Id流派表,指向ID为2的流派名称,即“Action”

当我尝试发布如下电影时,邮递员收到 415 错误

{
    "timestamp": "2020-08-11T03:57:31.792+00:00",
    "status": 415,
    "error": "Unsupported Media Type",
    "message": "",
    "path": "/video-library/movies/"
}

请教我哪里做错了

Movie.java

@Entity
@Table
public class Movie {
    
  @Id
  @GeneratedValue (strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private Integer id;
  private String title;
  private int rate;
  
  @Column(name = "numberInStock")
  private int numberInStock;
  
  
  @ManyToOne(targetEntity = Genre.class)
  @JoinColumn(name="genreId")
  private Genre genre;

  public Movie() {

  }

public Movie(Integer id, String title, int rate, int numberInStock, Genre genre) {
    super();
    this.id = id;
    this.title = title;
    this.rate = rate;
    this.numberInStock = numberInStock;
    this.genre = genre;
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getTitle() {
    return title;
}

public void setTitle(String title) {
    this.title = title;
}

public int getRate() {
    return rate;
}

public void setRate(int rate) {
    this.rate = rate;
}

public int getNumberInStock() {
    return numberInStock;
}

public void setNumberInStock(int numberInStock) {
    this.numberInStock = numberInStock;
}

@JsonManagedReference 
public Genre getGenre() {
    return genre;
}

public void setGenre(Genre genre) {
    this.genre = genre;
}


}

Genre.java

@Entity
@Table
public class Genre {

@Id
@Column(name="genreId")
@GeneratedValue(strategy = GenerationType.IDENTITY)

private Integer id;

@OneToMany(mappedBy="genre", cascade = CascadeType.ALL)
private Set<Movie> movie;

@Column(name ="genre")
private String genre;



public Genre() {

}



public Genre(Integer id, Set<Movie> movie, String genre) {
    super();
    this.id = id;
    this.movie = movie;
    this.genre = genre;
}



public Integer getId() {
    return id;
}



public void setId(Integer id) {
    this.id = id;
}

@JsonBackReference
public Set<Movie> getMovie() {
    return movie;
}


public void setMovie(Set<Movie> movie) {
    this.movie = movie;
}



public String getGenre() {
    return genre;
}



public void setGenre(String genre) {
    this.genre = genre;
}



}

MovieRestcontroller

@CrossOrigin(origins = "http://localhost:3000")
@RestController
@RequestMapping("/video-library")
public class MovieController {

  @Autowired
  private  MoiveRepository movieRepository;



  //CRATE
  //Add movie
  @PostMapping("/movies")
  public Movie createMovie(@RequestBody Movie movie)
  {
    return movieRepository.save(movie);
  }

  //READ
  //Get a list of all movies
  @GetMapping("/movies")
  public List<Movie> getAllMovie(){
    return movieRepository.findAll();
  }

  //Get single movie
  @GetMapping("/movies/{id}")
  public ResponseEntity<Movie> getMovieById(@PathVariable Integer id){
    Movie movie = movieRepository.findById(id).orElseThrow(()->
      new ResourseNotFoundException("404 Error: Movie not exist with the Given "+id));
    return ResponseEntity.ok(movie);
  }

  //UPDATE
  //Updated movie
  @PutMapping("/movies/{id}")
  public ResponseEntity <Movie> updateMovie(@PathVariable Integer id, @RequestBody Movie movieDetails){
    Movie movie = movieRepository.findById(id).orElseThrow((() ->
      new ResourseNotFoundException("404 Error: Movie not exist with the Given "+id)));


    movie.setTitle(movieDetails.getTitle());
    movie.setRate(movieDetails.getRate());
//    movie.setGenre(movieDetails.getGenre());
    movie.setNumberInStock(movieDetails.getNumberInStock());

    Movie updateMovie = movieRepository.save(movie);
    Map<String,Boolean> response = new HashMap<>();
    response.put("Movie Updated Successfully",Boolean.TRUE);
    return  ResponseEntity.ok(updateMovie);
  }

  //DELETE
  //Delete movie
  @DeleteMapping("/movies/{id}")
  public ResponseEntity <Map<String, Boolean>> deleteMovie(@PathVariable Integer id){
    Movie employee = movieRepository.findById(id)
      .orElseThrow((() -> new ResourseNotFoundException("404 Error: Movie not exist with the Given "+id)));
    movieRepository.delete(employee);
    Map<String,Boolean> response = new HashMap<>();
    response.put("Movie Deleted Successfully",Boolean.TRUE);
    return ResponseEntity.ok(response);
  }
  
  
}

流派控制器

@CrossOrigin(origins = "http://localhost:3000")
@RestController
@RequestMapping("/video-library")
public class GenreController {
    @Autowired
    public GenreRepository genreRepository;
    
    
      @PostMapping("/genre")
      public Genre createGenre(@RequestBody Genre genre)
      {
        return genreRepository.save(genre);
      }
      
      @GetMapping("/genre")
      public List<Genre> getAllGenre(){
        return genreRepository.findAll();
      }


      @GetMapping("/genre/{id}")
      public ResponseEntity<Genre> getGenreById(@PathVariable Integer id){
        Genre genre = genreRepository.findById(id).orElseThrow(()->
          new ResourseNotFoundException("404 Error: Genre not exist with the Given "+id));
        return ResponseEntity.ok(genre);
      }
}

【问题讨论】:

  • 您使用哪个客户端来测试您的 REST API?

标签: java spring spring-boot spring-mvc spring-data-jpa


【解决方案1】:

您使用哪个客户端来测试您的 REST API?

所有客户端都有选项让您在请求中设置 Content-type:application/json 标头。

在 Postman 中选择Body 选项卡,然后选择raw,然后将右侧的TEXT 更改为JSON

【讨论】:

  • 是的,我正在通过发送 JSON 进行测试,我确定我选择 Body > Raw > JSON
  • 我确信与关系映射有关,如果在流派类中注释掉 @OneToMany 和在 Movie 类中注释掉 @ManyToOne 以及它们的构造函数、设置器和获取器并执行 Post 方法对于电影,它采用其他三个属性,即“title”、“rate”、“numberInStock”。
【解决方案2】:

尝试在 @GetMapping@PostMapping 注释中使用 consumesproduces 属性,例如:

@PostMapping(path = "/genre",consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)

@GetMapping(path = "/movies/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)

您传递了错误的请求。您的请求应包含 genre 作为对象。 试试

{
  "title":"John Wick",
  "rate":8.2,
  "numberInStock":19,
  "genre":{"genreId":2}
}

【讨论】:

  • 感谢 Nitin 的回复,我已尝试按照您的建议添加属性,但仍然收到 415 响应,如果我在表格中手动添加数据,请从我得到的电影中执行 Get 方法以下响应``` {“id”:1,“title”:“John Wick”,“rate”:9,“numberInStock”:19,“genre”:{“id”:1,“genre”:“行动”}}```
  • 正如@tashkhisi 所建议的,尝试在 post 请求中添加 Content-type 并接受 header 作为 application/json 类型。
  • 我只想传递可以指向流派的genreId。流派表包含一个流派 ID 和流派。我的意图是存储类型,例如 1 用于动作,2 用于 comdey 等
  • 但是在您的 Movie 类中,您没有任何名为genreId 的变量,并且genre 是Genre 的对象。您正在尝试将 int 值传递给会失败的流派对象。您可以在主请求中将流派的 id 作为 "genre":{"genreId":2} 传递。我已经更新了。
  • 是否可以通过创建一个新变量来获取一个 int 值并将其分配给流派表中的流派 id,这样它就可以代替将另一个对象传递给请求?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-27
  • 2020-07-10
相关资源
最近更新 更多