I have two entities - User
and Song
:
User.class:
@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<>();
}
Song.class:
@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<>();
}
I want to delete a Song, but not delete a User.
I tried deleting it like this:
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()
But the error drops:
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".
I understand that the problem is due to the fact that in the spanning table users_songs
, which occurred due to the connection @OneToMany
.
I read a similar question in the STO and it says that you need to break the connection. how to delete the record from the join table in hibernate
I executed the following code:
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();
This code works, but I don't think it's quite right. Now the question. How do I delete a Song from a user? With the condition that the song should not cascade to delete the user.
Please help me solve this issue correctly. I'd really appreciate it.