Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public RsData<Integer> fetchMusicBrainzIds(
public RsData<Void> create(
@Valid @RequestBody CreateRequest reqBody
) {
artistService.createArtist(reqBody.artistName(), reqBody.artistGroup(), reqBody.artistType(), reqBody.genreName());
artistService.createArtist(reqBody.spotifyID(), reqBody.artistName(), reqBody.artistGroup(), reqBody.artistType(), reqBody.genreName());
return RsData.success("아티스트 생성이 완료되었습니다.", null);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.back.web7_9_codecrete_be.domain.artists.dto.request;

import com.back.web7_9_codecrete_be.domain.artists.entity.ArtistType;
import com.back.web7_9_codecrete_be.domain.artists.entity.Genre;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public record CreateRequest(
@NotBlank
@Size(max = 30, message = "Spotify ID 는 필수로 입력해야합니다.")
@Schema(description = "Spotify ID 입니다.")
String spotifyID,

@NotBlank(message = "아티스트 이름은 필수로 입력해야합니다.")
@Size(max = 200, message = "아티스트 이름은 200자를 넘길 수 없습니다.")
@Schema(description = "아티스트 이름입니다.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.back.web7_9_codecrete_be.domain.artists.entity.Artist;
import io.swagger.v3.oas.annotations.media.Schema;

import java.util.List;

public record ArtistListResponse(
@Schema(description = "아티스트 아이디입니다.")
Long id,
Expand All @@ -13,8 +15,8 @@ public record ArtistListResponse(
@Schema(description = "아티스트 소속 그룹입니다. 아티스트 이름이 그룹인 경우, null 로 처리됩니다.")
String artistGroup,

@Schema(description = "장르 이름입니다.")
String genreName,
@Schema(description = "장르입니다.")
List<String> genres,

@Schema(description = "받은 좋아요 수(찜한 사람 수) 입니다.")
int likeCount,
Expand All @@ -25,24 +27,33 @@ public record ArtistListResponse(
@Schema(description = "로그인한 유저의 좋아요 여부입니다. 비회원인 경우 false입니다.")
Boolean isLiked
) {
public static List<String> getGenre(Artist artist) {
return artist.getArtistGenres().stream()
.map(ag -> ag.getGenre().getGenreName())
.distinct()
.toList();
}

public static ArtistListResponse from(Artist artist) {
List<String> genres = getGenre(artist);
return new ArtistListResponse(
artist.getId(),
artist.getArtistName(),
artist.getArtistGroup(),
artist.getGenre().getGenreName(),
genres,
artist.getLikeCount(),
artist.getImageUrl(),
false // 기본값은 false
);
}

public static ArtistListResponse from(Artist artist, boolean isLiked) {
List<String> genres = getGenre(artist);
return new ArtistListResponse(
artist.getId(),
artist.getArtistName(),
artist.getArtistGroup(),
artist.getGenre().getGenreName(),
genres,
artist.getLikeCount(),
artist.getImageUrl(),
isLiked
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.HashSet;
import java.util.Set;


@Entity
@Getter
Expand All @@ -28,9 +31,6 @@ public class Artist {
@Column(name = "artist_type")
private ArtistType artistType;

@ManyToOne(fetch = FetchType.LAZY)
private Genre genre;

@Column(name = "spotify_artist_id", unique = true)
private String spotifyArtistId;

Expand All @@ -46,19 +46,25 @@ public class Artist {
@Column(name = "image_url")
private String imageUrl;

@OneToMany(mappedBy = "artist", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<ArtistGenre> artistGenres = new HashSet<>();

public Artist(String spotifyArtistId, String artistName, String artistGroup, ArtistType artistType, Genre genre) {
this.spotifyArtistId = spotifyArtistId;
this.artistName = artistName;
this.artistGroup = artistGroup; // 옵션 B: seed에서는 null
this.artistType = artistType; // 옵션 B: seed에서는 "SINGER"
this.genre = genre;
if (genre != null) {
addGenre(genre);
}
}

public Artist(String artistName, String artistGroup, ArtistType artistType, Genre genre) {
// 장르 없이 생성하는 생성자 (시드 데이터용)
public Artist(String spotifyArtistId, String artistName, String artistGroup, ArtistType artistType) {
this.spotifyArtistId = spotifyArtistId;
this.artistName = artistName;
this.artistGroup = artistGroup;
this.artistType = artistType;
this.genre = genre;
}

public void updateProfile(String nameKo, String artistGroup, ArtistType artistType) {
Expand All @@ -79,10 +85,6 @@ public void changeType(ArtistType type) {
this.artistType = type;
}

public void changeGenre(Genre genre) {
this.genre = genre;
}

public void increaseLikeCount() {
this.likeCount++;
}
Expand All @@ -96,4 +98,16 @@ public void decreaseLikeCount() {
public void setMusicBrainzId(String musicBrainzId) {
this.musicBrainzId = musicBrainzId;
}

public void addGenre(Genre genre) {
this.artistGenres.add(new ArtistGenre(this, genre));
}

public void replaceGenres(Set<Genre> genres) {
this.artistGenres.clear(); // orphanRemoval=true라 매핑 row 삭제됨
for (Genre genre : genres) {
this.artistGenres.add(new ArtistGenre(this, genre));
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.back.web7_9_codecrete_be.domain.artists.entity;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ArtistGenre {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "artist_genre_id")
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "artist_id", nullable = false)
private Artist artist;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "genre_id", nullable = false)
private Genre genre;

public ArtistGenre(Artist artist, Genre genre) {
this.artist = artist;
this.genre = genre;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,8 @@ public class Genre {
@Column(name = "genre_name", nullable = false, length = 30)
private String genreName;

@Column(name = "genre_group", length = 30)
private String genreGroup;

@Column(name = "genre_memo")
private String genreMemo;

public Genre(String genreName, String genreGroup, String genreMemo) {
public Genre(String genreName) {
this.genreName = genreName;
this.genreGroup = genreGroup;
this.genreMemo = genreMemo;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@Repository
public interface ArtistRepository extends JpaRepository<Artist, Long> {
boolean existsBySpotifyArtistId(String spotifyArtistId);
java.util.Optional<Artist> findBySpotifyArtistId(String spotifyArtistId);

@Query("SELECT a FROM Artist a WHERE a.nameKo IS NULL ORDER BY a.id ASC")
List<Artist> findByNameKoIsNullOrderByIdAsc(Pageable pageable);
Expand All @@ -23,7 +24,16 @@ public interface ArtistRepository extends JpaRepository<Artist, Long> {
boolean existsByNameKo(String nameKo);

List<Artist> findTop5ByArtistGroupAndIdNot(String artistGroup, long excludeId);
List<Artist> findTop5ByGenreIdAndIdNot(Long genreId, long excludeId);

@Query("""
SELECT DISTINCT a FROM Artist a
JOIN a.artistGenres ag
WHERE ag.genre.id = :genreId AND a.id != :excludeId
ORDER BY a.likeCount DESC
""")
List<Artist> findTop5ByGenreIdAndIdNot(@org.springframework.data.repository.query.Param("genreId") Long genreId,
@org.springframework.data.repository.query.Param("excludeId") long excludeId,
Pageable pageable);

List<Artist> findAllByArtistNameContainingIgnoreCaseOrNameKoContainingIgnoreCase(String artistName1, String artistName2);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface GenreRepository extends JpaRepository<Genre, Long> {
Optional<Genre> findByGenreName(String genreName);
List<Genre> findByGenreNameIn(List<String> genreNames);
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ public int setArtist() {
}

@Transactional
public Artist createArtist(String artistName, String artistGroup, ArtistType artistType, String genreName) {
public Artist createArtist(String spotifyArtistId, String artistName, String artistGroup, ArtistType artistType, String genreName) {
Genre genre = genreService.findByGenreName(genreName);
if(artistRepository.existsByArtistName(artistName) || artistRepository.existsByNameKo(artistName)) {
throw new BusinessException(ArtistErrorCode.ARTIST_ALREADY_EXISTS);
}
Artist artist = new Artist(artistName, artistGroup, artistType, genre);
Artist artist = new Artist(spotifyArtistId, artistName, artistGroup, artistType, genre);
artistRepository.save(artist);
return artist;
}
Expand Down Expand Up @@ -114,13 +114,19 @@ public ArtistDetailResponse getArtistDetail(Long artistId, User user) {
isLiked = artistLikeRepository.existsByArtistAndUser(artist, user);
}

// 첫 번째 장르 ID 가져오기 (없으면 null)
Long genreId = artist.getArtistGenres().stream()
.findFirst()
.map(ag -> ag.getGenre().getId())
.orElse(null);

return spotifyService.getArtistDetail(
artist.getSpotifyArtistId(),
artist.getArtistGroup(),
artist.getArtistType(),
likeCount,
artist.getId(),
artist.getGenre() != null ? artist.getGenre().getId() : null,
genreId,
isLiked
);
}
Expand Down Expand Up @@ -149,7 +155,7 @@ public void updateArtist(Long id, UpdateRequest req) {

if (req.genreName() != null && !req.genreName().isBlank()) {
Genre genre = genreService.findByGenreName(req.genreName().trim());
artist.changeGenre(genre);
artist.replaceGenres(Set.of(genre));
changed = true;
}

Expand Down
Loading