Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Spring Boot中使用JPA从两者之间具有一对一关系的实体中删除对象_Java_Spring Boot_Jpa_Orm - Fatal编程技术网

Java 在Spring Boot中使用JPA从两者之间具有一对一关系的实体中删除对象

Java 在Spring Boot中使用JPA从两者之间具有一对一关系的实体中删除对象,java,spring-boot,jpa,orm,Java,Spring Boot,Jpa,Orm,下午好,我正在使用一个RESTAPI,其中我有一个包含许多歌曲的播放列表,为此我使用了JPA,它的优点使我能够建立两者之间的关系。现在,如果我想删除一首已经添加到播放列表中的歌曲,我无法删除,我将在下面向您展示我的课程 类播放列表 @Entity @Table(name = "PLAY_LIST") public class PlayList { @JsonIgnore @Id @GeneratedValue(strategy = Generatio

下午好,我正在使用一个RESTAPI,其中我有一个包含许多歌曲的播放列表,为此我使用了JPA,它的优点使我能够建立两者之间的关系。现在,如果我想删除一首已经添加到播放列表中的歌曲,我无法删除,我将在下面向您展示我的课程

类播放列表

@Entity
@Table(name = "PLAY_LIST")
public class PlayList {

    @JsonIgnore
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long id;

    //@JsonView(View.Get.class)
    @Column(name="name")
    private String name;

    //@JsonView(View.Get.class)
    @Column(name="description")
    private String description;

    //@JsonView(View.Get.class)
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "playList")
    private List<Song> songs = new ArrayList<>();

    @Transient
    public void addSong(Song song) {
        song.setPlayList(this);
        songs.add(song);
    }

    @Transient
    public void removeSong(Song song) {
        songs.remove(song);
    }

    public Long getId() {
        return this.id;
    }

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

    public String getName() {
        return this.name;
    }

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

    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


    public List<Song> getSongs() {
        return this.songs;
    }

    public void setSongs(List<Song> songs) {
        this.songs = songs;
    }
    
}
我的班长

@RestController
@RequestMapping("playlist")
public class PlayListController {

   @Autowired
   private PlayListService playListService;

   @Autowired
   private SongRepository songRepository;


   // Get playlist by id with songs belongs that playlist

   @GetMapping("/get/{id}")
   public Optional<PlayList> getPlayListByID(@PathVariable(value = "id") Long id) {

      Optional<PlayList> playList = playListService.getById(id);
      return playList;
   }

   @PostMapping("/create")
   public PlayList createPlayList(@RequestBody PlayListDTO playListDTO) {

      PlayList playList = new PlayList();

      playList.setName(playListDTO.getName());
      playList.setDescription(playListDTO.getDescription());
      playList.setSongs(new ArrayList<>());

      for (int x=0; x<playListDTO.getSongs().size(); x++) {

         Song songs=new Song();
         songs.setTitle(playListDTO.getSongs().get(x).getTitle());
         songs.setArtist(playListDTO.getSongs().get(x).getArtist());
         songs.setAlbum(playListDTO.getSongs().get(x).getAlbum());
         songs.setYear(playListDTO.getSongs().get(x).getYear());
         playList.addSong(songs);

      }
        return playListService.savePlayList(playList);
     }
   @PutMapping("/update/{id}")
   public PlayList updatePlayList(@PathVariable(value = "id") Long id,@RequestBody Song song){

      PlayList playList = playListService.getById(id).get();
      song.setPlayList(playList);
      playList.getSongs().add(song);
      playListService.savePlayList(playList);
      return playList;
   }
   
   @DeleteMapping("/delete/{id}")
   public PlayList deletePlayList(@PathVariable(value = "id") Long id,@RequestBody Song song){
      PlayList playList =playListService.getById(id).get();
      System.out.println(playList.getSongs());
      playList.removeSong(song);
      System.out.println(playList.getSongs());
      return playList;
   }

}
现在,为了消除,我正在传递播放列表的id和歌曲的请求(没有在BD中自动创建的歌曲id的对象),但是,我无法从播放列表中消除歌曲,并且在日志级别,它在控制台中执行打印时返回此消息

例如,我想删除以下歌曲:

但是它不会被删除,它会将相同的列表返回给我


我是否错过了一些可以删除歌曲而不必删除播放列表的功能?

使用
播放列表中的所有歌曲列表删除歌曲不是一个好主意。
没有用于
@OneToMany
关联的联接表。因此,我们可以使用
song
table更简单地删除歌曲(这是
@OneToMany
的联接表不方便的主要原因)

为此,您需要一个歌曲id,并且需要使用
crudepository.deleteById()
方法。 您可以使用完整的组合(标题、艺术家、专辑、年份),但在JSON中添加歌曲id要简单得多

最好使用此端点URL删除歌曲

/{playlyid}/songs/{songId}

您不需要删除URL中的
部分,您已经使用了删除HTTP方法

为什么您的代码不起作用

  • 使用列表中的delete方法不正确
  • songs.remove()
    在列表中找不到
    song
    list.remove()
    通过引用查找歌曲。它需要有一个开放的持久上下文,并从中获取一首歌曲,才能在列表中找到它

  • 不使用事务(打开的持久上下文)让Hibernate知道某首歌曲已被删除,Hibernate必须更新数据库
  • 因此,这是一个有效的方案

    start @Transactional
      Spring starts a database transaction
      Spring opens a persistent context
      load PlayList
      load a song from the database (using id or other song attributes)
      delete a song from PlayList songs (or delete a song from PlayList songs using id)
    end @Transactional
        
    Hibernate flushes changes and delete a song in the database
    persistent context is closed
    database transaction is committed
    

    非常感谢,我发现删除歌曲的好方法是通过对象歌曲和方法http delete删除,发送歌曲id。使用OneToMany的缺点是什么?我很好奇Spotify播放列表在现实生活中是如何通过关系工作的,这就是我想要做的this@CesarJusto如果要使用
    @OneToMany
    收藏删除一首歌曲,必须从数据库中加载所有歌曲,从收藏中删除一首歌曲,并与歌曲一起保存播放列表。Hibernate将删除一条记录,当然不会更新所有内容。@CesarJusto使用歌曲集可能很有用,如果用户更改了歌曲集的一些元素,那么您可以使用
    merge()
    方法添加或删除多个元素。要使用@OneToMay删除歌曲,我使用实体song和remove方法删除一首歌曲,然后使用相同的id?再次保存列表,或者按照这种情况下的过程,因为我尝试使用song实体中的remove函数进行删除,然后通过save函数再次保存,但它仍然没有返回更新的列表,或者我不知道它是否创建了一个新列表
    {
        "name": "Lista 1",
        "description": "Lista de reproduccion 2020 spotify",
        "songs": [
            {
                "title": "Tan Enamorados",
                "artist": "CNCO",
                "album": "Tan Enamorados",
                "year": 2020
            },
            {
                "title": "Hawai",
                "artist": "Maluma",
                "album": "PAPI JUANCHO",
                "year": 2020
            }
        ]
    }
    
    @Transient
    public void removeSong(Song song) {
        songs.remove(song);
    }
    
    start @Transactional
      Spring starts a database transaction
      Spring opens a persistent context
      load PlayList
      load a song from the database (using id or other song attributes)
      delete a song from PlayList songs (or delete a song from PlayList songs using id)
    end @Transactional
        
    Hibernate flushes changes and delete a song in the database
    persistent context is closed
    database transaction is committed