Sping Boot -添加歌曲后无法使用get from Postman:服务器错误(Spring)和内部服务器错误(postman)

68bkxrlz  于 2022-12-13  发布在  Spring
关注(0)|答案(1)|浏览(134)

我们的老师要求我们创建一个Sping Boot 应用程序来使用DTO以一对多的关系管理歌曲和专辑,但我们需要在控制器中手动进行Map,我们不能使用外部库。问题是,无论我如何尝试更改方法,它总是导致Spring上的错误(我们使用PostgreSQL,在pgadmin中我可以看到数据,没有问题)。
例如,对于我现在共享的代码,我最初可以在歌曲和专辑上使用get,但如果我添加了一首新歌,get方法将导致NoSuchElementException,
特别是这一行:at com.newplaylist.controller.SongController.getSongs(SongController.java:55)
它指向这一行:songs.add(new SongDTO((Song) iterator.next(), iterator.next().getAlbum()));
我也收到了一个500内部服务器错误的 Postman 。提前感谢帮助,如果需要我可以添加完整的异常跟踪。

  • 歌曲DTO
import com.newplaylist.entity.Album;
import com.newplaylist.entity.Song;

public class SongDTO {

    private Integer id;
    private String author, title;
    private AlbumDTO album;
    
    public SongDTO() {
            
    }
    
    public SongDTO(Song song) { 
        this.id = song.getId();
        this.author = song.getAuthor();
        this.title = song.getTitle();
    }
    
    public SongDTO(Song song, Album album) {    
        this.id = song.getId();
        this.author = song.getAuthor();
        this.title = song.getTitle();
        this.album = new AlbumDTO(album, true);
    }
    
    // getters and setters...

}
  • 相册DTO
import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.newplaylist.entity.Album;
import com.newplaylist.entity.Song;

public class AlbumDTO {
    
    private Integer id;
    private String name;
    private String production;
    private Set<SongDTO> songs;
    
    public AlbumDTO() {
    }
    
    public AlbumDTO(Album album) {
        this.id = album.getId();
        this.name = album.getName();
        this.production = album.getProduction();
    }
    
    public AlbumDTO(Album album, boolean lazy) {
        this.id = album.getId();
        this.name = album.getName();
        this.production = album.getProduction();
        songs = new HashSet<SongDTO>();
        album.getSongs();
        
        if (!lazy) {
            for (Iterator<Song> iterator = album.getSongs().iterator(); iterator.hasNext();) {
                songs.add(new SongDTO((Song) iterator.next()));
            }
        }
    }

    // getters and setters...

}
  • 乐曲控制器
package com.newplaylist.controller;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.newplaylist.dto.AlbumDTO;
import com.newplaylist.dto.SongDTO;
import com.newplaylist.entity.Album;
import com.newplaylist.entity.Song;
import com.newplaylist.service.SongService;

@RestController
@RequestMapping("/song")
public class SongController {

    @Autowired
    SongService songService;
    
    public void init() {
    }
    
    @PostMapping("/add")
    public ResponseEntity<?> addSong(@RequestBody Song song) {
        try {
            return new ResponseEntity<SongDTO>(new SongDTO(songService.addSong(song), song.getAlbum()), HttpStatus.CREATED);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<Object>(e.getStackTrace(), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
    
    @GetMapping("/all")
    public ResponseEntity<Collection<SongDTO>> getSongs() {
        Collection<SongDTO> songs = new ArrayList<>();
        
        try {
            for (Iterator<Song> iterator = songService.getSongs().iterator(); iterator.hasNext();) {
                songs.add(new SongDTO((Song) iterator.next(), iterator.next().getAlbum()));
            }
            
            return new ResponseEntity<Collection<SongDTO>>(songs, HttpStatus.OK);
            
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
    
}
  • 相册控制器
package com.newplaylist.controller;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.newplaylist.dto.AlbumDTO;
import com.newplaylist.dto.SongDTO;
import com.newplaylist.entity.Album;
import com.newplaylist.entity.Song;
import com.newplaylist.service.AlbumService;

@RestController
@RequestMapping("/album")
public class AlbumController {

    @Autowired
    AlbumService albumService;
    
    @PostMapping("/add")
    public ResponseEntity<?> addAlbum(@RequestBody Album album) {
        try {
            return new ResponseEntity<AlbumDTO>(new AlbumDTO(albumService.addAlbum(album), true), HttpStatus.CREATED);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<Object>(e.getStackTrace(), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
    
    @GetMapping("/all")
    public ResponseEntity<Collection<AlbumDTO>> getAlbums() {
        Collection<AlbumDTO> albums = new ArrayList<>();
        
        try {
            for (Iterator<Album> iterator = albumService.getAlbums().iterator(); iterator.hasNext();) {
                albums.add(new AlbumDTO((Album) iterator.next(), false));
            }

            return new ResponseEntity<Collection<AlbumDTO>>(albums, HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
        }
        
    }

}
  • 相册(实体)
package com.newplaylist.entity;

import java.util.Set;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;

@Entity
public class Album {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private String production;
    
    
    //@JsonBackReference        // per scegliere quale reference stampare, altrimenti andrebbe in loop infinito
    @OneToMany(mappedBy = "album", cascade = CascadeType.ALL)
    private Set<Song> songs;
    
    public Album() {
        super();
    }

    public Album(Integer id, String name, String production, Set<Song> songs) {
        super();
        this.id = id;
        this.name = name;
        this.production = production;
        this.songs = songs;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getProduction() {
        return production;
    }

    public void setProduction(String production) {
        this.production = production;
    }

    public Set<Song> getSongs() {
        return songs;
    }

    public void setSongs(Set<Song> songs) {
        this.songs = songs;
    }
    
}
  • 歌曲(实体)
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;

@Entity
public class Song {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String author, title;
    
//  @OneToOne
//  @JoinColumn(name = "album")     // campo album della tab song. questo campo contiene un id che si collega all'entità Album, perciò fai l'inner join con essa.
//  private Album album;
    
//  @ManyToOne
//  @JoinColumn(name = "playlist")
//  private Playlist playlist;
    
    @ManyToOne
    @JoinColumn(name = "album", nullable = false)
    //@JsonManagedReference
    private Album album;
    
    public Song() {}

    public Song(Integer id, String author, String title) {
        super();
        this.id = id;
        this.author = author;
        this.title = title;
    }

    public Song(Integer id, String author, String title, Album album) {
        super();
        this.id = id;
        this.author = author;
        this.title = title;
        this.album = album;
    }

    // getters and setters
    
}

我相信问题出在这些类中的一个,但是如果你需要其他的东西,我可以把项目上传到GitHub上。

mzillmmw

mzillmmw1#

你需要这样的东西

try {
        for (Iterator<Song> iterator = songService.getSongs().iterator(); iterator.hasNext();) {
            Song currentSong = iterator.next();
            songs.add(new SongDTO(currentSong, currentSong.getAlbum()));
        }

调用iterator.next()将总是获取一首新歌,这意味着iterator.next().getAlbum()将获取与集合中下一首歌对应的专辑,而不是第一次调用iterator.next()时已经获取的当前专辑。此外,如果歌曲数量为奇数,它将导致异常。

相关问题