【问题标题】:Deleting Entities @OneToMany @ManyToOne. Key is still referenced from table删除实体@OneToMany @ManyToOne。键仍然从表中引用
【发布时间】:2021-07-06 16:04:06
【问题描述】:

我有两个实体 - UserSong

用户类:

@Entity
@Table(name = "users")
public class User {
    
   @Id
   @Column(name = "user_id")
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
    
   @Column(name = "first_name")
   private String firstName;
    
   @Column(name = "last_name")
   private String lastName;
    
   @Column(name = "login",unique = true)
   private String login;
    
   @Column(name = "password")
   private String password;
    
   @Column(name = "token")
   private UUID token;
    
   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
   @JoinTable(
      name = "users_songs",
      joinColumns = @JoinColumn(
         name = "u_id",
         referencedColumnName = "user_id"
      ),
      inverseJoinColumns = @JoinColumn(
         name = "s_id",
         referencedColumnName = "song_id"
      )
   )
   private List<Song> songs = new ArrayList<>();
}

歌曲类:

@Entity
@Table(name = "songs")
public class Song {
        
   @Id
   @Column(name = "song_id")
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
        
   @Column(name = "song_title")
   private String songTitle;
        
   @Column(name = "composer_name")
   @ElementCollection(fetch = FetchType.EAGER)
   @CollectionTable(name = "composers")
   @OnDelete(action = OnDeleteAction.CASCADE)
   @JoinColumn(name = "composer_id")
   private Set<String> composer;
        
   @Column(name = "author_of_words_name")
   @ElementCollection(fetch = FetchType.EAGER)
   @CollectionTable(name = "author_of_words")
   @OnDelete(action = OnDeleteAction.CASCADE)
   @JoinColumn(name = "authorOfWords_id")
   private Set<String> authorOfWords;
        
   @Column(name = "song_artist")
   private String songArtist;
        
   @Column(name = "song_timing")
   private int songTiming;
        
   @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
   @JoinColumn(name = "user_id_key")
   private User user;
        
   @Column(name = "rate_value")
   @ElementCollection(fetch = FetchType.EAGER)
   @CollectionTable(name = "rating")
   @MapKeyColumn(name = "login")
   @OnDelete(action = OnDeleteAction.CASCADE)
   @JoinColumn
   private final Map<String, Integer> rating = new HashMap<>();
        
   @Column
   @ElementCollection(fetch = FetchType.EAGER)
   @CollectionTable(name = "comment")
   @MapKeyColumn(name = "login")
   @OnDelete(action = OnDeleteAction.CASCADE)
   @JoinColumn
   private final Map<String, String> comments = new HashMap<>();
}

我想删除歌曲,但不想删除用户。

我尝试这样删除它:

Query query = session.createQuery("DELETE Song s WHERE s.user = :user AND s.songTitle = :songTitle");
query.setParameter("user", user);
query.setParameter("songTitle", songTitle);
query.executeUpdate()

但错误下降:

    Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement...
    Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on table "songs" violates foreign key constraint "fka7me64vk6jtx81wt2ggbvm6ur" on table "users_songs"
     Key (song_id)=(28) is still referenced from table "users_songs".

我了解问题是由于在生成表users_songs 中,由于连接@OneToMany 而发生的。

我在 STO 中阅读了一个类似的问题,它说您需要断开连接。 how to delete the record from the join table in hibernate

我执行了以下代码:

List<Song> collect = user.getSongs().stream().filter(s -> !s.getSongTitle().equals(songTitle)).collect(Collectors.toList());
user.setSongs(collect);
session.update(user);
Query query = session.createQuery("DELETE Song s WHERE s.songTitle = :songTitle");
query.setParameter("songTitle", songTitle);
query.executeUpdate();

此代码有效,但我认为它不太正确。现在的问题。如何删除用户的歌曲?条件是歌曲不能级联删除用户。

请帮我正确解决这个问题。我真的很感激。

【问题讨论】:

    标签: java hibernate hql hibernate-mapping hibernate-criteria


    【解决方案1】:

    您可以指定ON DELETE CASCADEforeign key constraint fka7me64vk6jtx81wt2ggbvm6ur 在表格users_songs 上,如下所示:

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(
       name = "users_songs",
       joinColumns = @JoinColumn(
          name = "u_id",
          referencedColumnName = "user_id"
       ),
       inverseJoinColumns = @JoinColumn(
          name = "s_id",
          referencedColumnName = "song_id"
       ),
       inverseForeignKey = @ForeignKey(
          name = "users_songs_songs_FK",  // fka7me64vk6jtx81wt2ggbvm6ur renamed to users_songs_songs_FK
          foreignKeyDefinition = "FOREIGN KEY (s_id) REFERENCES songs(song_id) ON DELETE CASCADE"
       )
    )
    private List<Song> songs = new ArrayList<>();
    

    在重新生成数据库架构后,您的初始查询应该会按预期工作。

    【讨论】:

      猜你喜欢
      • 2020-06-25
      • 1970-01-01
      • 2017-01-31
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      • 2011-11-15
      • 1970-01-01
      相关资源
      最近更新 更多