package musicstore.musicselling.Entity;
import java.util.Set;
import java.util.HashSet;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
@Entity
@Table(name = "artist")
public class Artist {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long artistId;
private String artistName;
private String artistBio;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "artist_song", joinColumns = {
@JoinColumn(name = "artist_id", referencedColumnName = "artistId") }, inverseJoinColumns = {
@JoinColumn(name = "song_id", referencedColumnName = "songId") })
private Set<Song> songs = new HashSet<>();
public Artist() {
}
public Artist(String artistName, String artistBio) {
this.artistName = artistName;
this.artistBio = artistBio;
}
public Long getArtistId() {
return artistId;
}
public String getArtistName() {
return artistName;
}
public void setArtistName(String artistName) {
this.artistName = artistName;
}
public String getArtistBio() {
return artistBio;
}
public void setArtistBio(String artistBio) {
this.artistBio = artistBio;
}
public Set<Song> getSongs() {
return songs;
}
public void setSongs(Set<Song> songs) {
this.songs = songs;
}
public void addSong(Song song) {
this.songs.add(song);
song.getArtists().add(this);
}
}
package musicstore.musicselling.Entity;
import java.util.Set;
import java.util.HashSet;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
@Entity
@Table(name = "song")
public class Song {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long songId;
private String songName;
private long songStream;
@ManyToMany(mappedBy = "songs", fetch = FetchType.EAGER)
private Set<Artist> artists = new HashSet<>();
public Song() {
}
public Song(String songName, long songStream) {
this.songName = songName;
this.songStream = songStream;
this.artists = new HashSet<>();
}
public Long getSongId() {
return songId;
}
public String getSongName() {
return songName;
}
public void setSongName(String songName) {
this.songName = songName;
}
public long getSongStream() {
return songStream;
}
public void setSongStream(long songStream) {
this.songStream = songStream;
}
public Set<Artist> getArtists() {
return artists;
}
public void setArtists(Set<Artist> artists) {
this.artists = artists;
}
public void addArtist(Artist artist) {
this.artists.add(artist);
artist.getSongs().add(this);
}
}
package musicstore.musicselling;
import java.util.Set;
import java.util.HashSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import jakarta.transaction.Transactional;
import musicstore.musicselling.Entity.Artist;
import musicstore.musicselling.Entity.Song;
import musicstore.musicselling.Repository.ArtistRepository;
import musicstore.musicselling.Repository.SongRepository;
@SpringBootApplication
public class MusicsellingApplication {
@Autowired
private SongRepository songRepository;
@Autowired
private ArtistRepository artistRepository;
public static void main(String[] args) {
SpringApplication.run(MusicsellingApplication.class, args);
}
@Bean
@Transactional
public CommandLineRunner commandLineRunner() {
return args -> {
// create artists
Artist artist1 = new Artist("Sơn Tùng M-TP", "Vietnamese singer-songwriter and actor.");
Artist artist2 = new Artist("tlinh", "tlinh is a Vietnamese independent singer and rapper.");
Artist artist3 = new Artist("RPT MCK", "RPT MCK is a Vietnamese singer and rapper based in Ha Noi.");
// save artists
artistRepository.save(artist1);
artistRepository.save(artist2);
artistRepository.save(artist3);
// Create songs and add artists
Song song1 = new Song("nếu lúc đó", 3794587);
song1.addArtist(artist2);
Song song2 = new Song("Chạy Ngay Đi", 234879825);
song2.addArtist(artist1);
Song song3 = new Song("Hãy Trao Cho Anh", 2387532);
song3.addArtist(artist1);
Song song4 = new Song("Chỉ Một Đêm Nữa Thôi (feat. tlinh)", 782643);
song4.addArtist(artist2);
song4.addArtist(artist3);
Song song5 = new Song("Em Là Châu Báu", 298374);
song5.addArtist(artist2);
song5.addArtist(artist3);
// save songs
songRepository.save(song1);
songRepository.save(song2);
songRepository.save(song3);
songRepository.save(song4);
songRepository.save(song5);
};
}
}
package musicstore.musicselling.Repository;
import org.springframework.data.jpa.repository.JpaRepository;
import musicstore.musicselling.Entity.Artist;
public interface ArtistRepository extends JpaRepository<Artist, Long> {
}
package musicstore.musicselling.Repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import musicstore.musicselling.Entity.Song;
@Repository
public interface SongRepository extends JpaRepository<Song, Long> {
}
这是我的代码,当我尝试运行应用程序时,artist_song 表没有填充任何数据,尽管其他两个表都填充了数据。
谁能告诉我artist_song表的数据没有填充的原因吗?
我尝试了很多方法,包括将 FetchType 从 LAZY 更改为 EAGER,但仍然不起作用
该问题与级联操作有关。您声明
Artist
为关系的所有者方,而您的目标方是 Song
。您首先存储艺术家,然后将这些艺术家添加到歌曲中,最后在应该相反的情况下保存这些歌曲。顺便说一句,当您在所有者端使用属性CascadeType.ALL
时,不需要先保存目标端,然后将目标端添加到所有者端并保存。您可以先将目标端添加到所有者端,然后保存(所有者端)。
您有两个选择,将
Song
设置为主侧或修改在数据库中存储实体的方式。
第一个选项:
在你的班级
Song
:
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "artist_song",
joinColumns = { @JoinColumn(name = "song_id", nullable = false) },
inverseJoinColumns = {@JoinColumn(name = "artist_id", nullable = false)
})
private Set<Artist> artists = new HashSet<>();
在你的班级
Artist
:
@ManyToMany(mappedBy = "artists")
private Set<Song> songs = new HashSet<>();
坚持类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import app.entity.Artist;
import app.entity.Song;
import app.repository.ArtistRepository;
import app.repository.SongRepository;
import jakarta.transaction.Transactional;
@Component
public class Persistence implements CommandLineRunner {
@Autowired
private ArtistRepository artistRepository;
@Autowired
private SongRepository songRepository;
@Override
@Transactional
public void run(String... args) throws Exception {
// Create artists
Artist artist1 = new Artist("Sơn Tùng M-TP", "Vietnamese singer-songwriter and actor.");
Artist artist2 = new Artist("tlinh", "tlinh is a Vietnamese independent singer and rapper.");
Artist artist3 = new Artist("RPT MCK", "RPT MCK is a Vietnamese singer and rapper based in Ha Noi.");
// Create songs and add artists
Song song1 = new Song("nếu lúc đó", 3794587);
song1.addArtist(artist2);
Song song2 = new Song("Chạy Ngay Đi", 234879825);
song2.addArtist(artist1);
Song song3 = new Song("Hãy Trao Cho Anh", 2387532);
song3.addArtist(artist1);
Song song4 = new Song("Chỉ Một Đêm Nữa Thôi (feat. tlinh)", 782643);
song4.addArtist(artist2);
song4.addArtist(artist3);
Song song5 = new Song("Em Là Châu Báu", 298374);
song5.addArtist(artist2);
song5.addArtist(artist3);
// Save songs, which will cascade and save artists as well
songRepository.save(song1);
songRepository.save(song2);
songRepository.save(song3);
songRepository.save(song4);
songRepository.save(song5);
}
}
第二个选项:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import app.entity.Artist;
import app.entity.Song;
import app.repository.ArtistRepository;
import app.repository.SongRepository;
import jakarta.transaction.Transactional;
@Component
public class Persistence implements CommandLineRunner {
@Autowired
private ArtistRepository artistRepository;
@Autowired
private SongRepository songRepository;
@Override
@Transactional
public void run(String... args) throws Exception {
// Create songs
Song song1 = new Song("nếu lúc đó", 3794587);
Song song2 = new Song("Chạy Ngay Đi", 234879825);
Song song3 = new Song("Hãy Trao Cho Anh", 2387532);
Song song4 = new Song("Chỉ Một Đêm Nữa Thôi (feat. tlinh)", 782643);
Song song5 = new Song("Em Là Châu Báu", 298374);
// Create artists
Artist artist1 = new Artist("Sơn Tùng M-TP", "Vietnamese singer-songwriter and actor.");
Artist artist2 = new Artist("tlinh", "tlinh is a Vietnamese independent singer and rapper.");
Artist artist3 = new Artist("RPT MCK", "RPT MCK is a Vietnamese singer and rapper based in Ha Noi.");
// Establish relationships
artist1.addSong(song2);
artist1.addSong(song3);
artist2.addSong(song1);
artist2.addSong(song4);
artist2.addSong(song5);
artist3.addSong(song4);
artist3.addSong(song5);
// Save artists, which will cascade and save songs as well
artistRepository.save(artist1);
artistRepository.save(artist2);
artistRepository.save(artist3);
}
}
我将实体存储在一个名为
Persistence
的新类中,因为我复制了您的代码,它给了我一个例外:Detached Entity Passed to Persist
。
您仍然可以在
MusicsellingApplication
方法中的 commandLineRunner
类中实现它,但您必须删除所有者端的属性 cascade = CascadeType.PERSIST
。这是因为Spring也会尝试保存关联的对象(歌曲)。但是,此对象未附加到此会话(分离异常的原因)。