Skip to content

Commit da3db4a

Browse files
committed
Merge branch 'main' into feat/#255
2 parents cb6630c + 475d017 commit da3db4a

55 files changed

Lines changed: 2689 additions & 293 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ jobs:
1515
backend-test:
1616
runs-on: ubuntu-latest
1717

18+
services:
19+
redis:
20+
image: redis
21+
ports:
22+
- 6379:6379
23+
1824
env:
1925
SPRING_PROFILES_ACTIVE: test
2026
SPRING_DATASOURCE_URL: jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false

src/main/java/com/back/web7_9_codecrete_be/domain/artists/controller/ArtistsController.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22

33
import com.back.web7_9_codecrete_be.domain.artists.dto.response.*;
44
import com.back.web7_9_codecrete_be.domain.artists.entity.Artist;
5-
import com.back.web7_9_codecrete_be.domain.artists.entity.ArtistLike;
65
import com.back.web7_9_codecrete_be.domain.artists.entity.ArtistSort;
7-
import com.back.web7_9_codecrete_be.domain.artists.dto.request.CreateRequest;
86
import com.back.web7_9_codecrete_be.domain.artists.dto.request.SearchRequest;
9-
import com.back.web7_9_codecrete_be.domain.artists.dto.request.UpdateRequest;
107
import com.back.web7_9_codecrete_be.domain.artists.service.ArtistService;
11-
import com.back.web7_9_codecrete_be.domain.artists.service.ArtistEnrichService;
8+
import com.back.web7_9_codecrete_be.domain.artists.service.artistEnrichService.ArtistEnrichService;
129
import com.back.web7_9_codecrete_be.domain.users.entity.User;
1310
import com.back.web7_9_codecrete_be.global.rq.Rq;
1411
import com.back.web7_9_codecrete_be.global.rsData.RsData;
@@ -121,6 +118,13 @@ public RsData<List<ConcertListByArtistResponse>> concertList() {
121118
return RsData.success("찜한 아티스트 공연 리스트 조회 성공", artistService.getConcertList(user.getId()));
122119
}
123120

121+
@Operation(summary = "찜한 아티스트 리스트 생성", description = "로그인한 유저가 찜한 아티스트 목록을 반환합니다.")
122+
@GetMapping("/likes")
123+
public RsData<List<LikeArtistsResponse>> likeArtists() {
124+
User user = rq.getUser();
125+
return RsData.success("찜한 아티스트 목록 조회 성공", artistService.findLikeArtistsByUserid(user));
126+
}
127+
124128
@Operation(summary = "아티스트 찜 여부 반환", description = "아티스트 Id 를 통해 로그인한 유저가 해당 아티스트를 찜했는지 여부를 반환합니다.")
125129
@GetMapping("/likes/{artistId}")
126130
public RsData<LikeArtistResponse> isLiked(
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.back.web7_9_codecrete_be.domain.artists.dto.response;
2+
3+
import com.back.web7_9_codecrete_be.domain.artists.entity.Artist;
4+
import com.back.web7_9_codecrete_be.domain.concerts.entity.Concert;
5+
import io.swagger.v3.oas.annotations.media.Schema;
6+
7+
public record LikeArtistsResponse(
8+
@Schema(description = "아티스트 아이디입니다.")
9+
Long id,
10+
11+
@Schema(description = "아티스트 이름입니다.")
12+
String artistName,
13+
14+
@Schema(description = "한국어 기준 아티스트 이름 입니다.")
15+
String nameKo,
16+
17+
@Schema(description = "아티스트 프로필 사진 URL 입니다.")
18+
String imageUrl
19+
) {
20+
public static LikeArtistsResponse from(Artist artist) {
21+
return new LikeArtistsResponse(
22+
artist.getId(),
23+
artist.getArtistName(),
24+
artist.getNameKo(),
25+
artist.getImageUrl()
26+
);
27+
}
28+
}

src/main/java/com/back/web7_9_codecrete_be/domain/artists/dto/response/SearchResponse.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import io.swagger.v3.oas.annotations.media.Schema;
55

66
public record SearchResponse(
7+
@Schema(description = "아티스트 id 입니다.")
8+
Long id,
9+
710
@Schema(description = "아티스트 이름입니다.")
811
String artistName,
912

@@ -14,14 +17,21 @@ public record SearchResponse(
1417
String artistGroup,
1518

1619
@Schema(description = "받은 총 좋아요 수(찜한 수) 입니다.")
17-
int likeCount
20+
int likeCount,
21+
22+
@Schema(description = "아티스트 이미지 URL 입니다.")
23+
String imageUrl
24+
25+
1826
) {
1927
public static SearchResponse from(Artist artist) {
2028
return new SearchResponse(
29+
artist.getId(),
2130
artist.getArtistName(),
2231
artist.getNameKo(),
2332
artist.getArtistGroup(),
24-
artist.getLikeCount()
33+
artist.getLikeCount(),
34+
artist.getImageUrl()
2535
);
2636
}
2737
}

src/main/java/com/back/web7_9_codecrete_be/domain/artists/entity/Artist.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ public class Artist {
2727
@Column(name = "artist_group")
2828
private String artistGroup;
2929

30-
@Enumerated(EnumType.STRING)
30+
@Convert(converter = ArtistTypeConverter.class)
3131
@Column(name = "artist_type")
3232
private ArtistType artistType;
3333

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

37-
@Column(name = "musicbrainz_id")
37+
@Column(name = "musicbrainz_id", unique = true)
3838
private String musicBrainzId;
3939

4040
@Column(name = "name_ko", length = 200)
@@ -43,6 +43,9 @@ public class Artist {
4343
@Column(name = "real_name", length = 200)
4444
private String realName;
4545

46+
@Column(name = "description", columnDefinition = "TEXT")
47+
private String description;
48+
4649
@Column(name = "like_count", nullable = false)
4750
private int likeCount = 0;
4851

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.back.web7_9_codecrete_be.domain.artists.entity;
2+
3+
import jakarta.persistence.AttributeConverter;
4+
import jakarta.persistence.Converter;
5+
import lombok.extern.slf4j.Slf4j;
6+
7+
@Slf4j
8+
@Converter(autoApply = true)
9+
public class ArtistTypeConverter implements AttributeConverter<ArtistType, String> {
10+
11+
@Override
12+
public String convertToDatabaseColumn(ArtistType attribute) {
13+
if (attribute == null) {
14+
return null;
15+
}
16+
return attribute.name();
17+
}
18+
19+
@Override
20+
public ArtistType convertToEntityAttribute(String dbData) {
21+
if (dbData == null || dbData.isBlank()) {
22+
return null;
23+
}
24+
25+
// 숫자로 저장된 잘못된 값 처리 (예: "0", "1", "2")
26+
if (dbData.matches("\\d+")) {
27+
log.warn("잘못된 artist_type 값 발견 (숫자): {}, null로 처리", dbData);
28+
return null;
29+
}
30+
31+
try {
32+
return ArtistType.valueOf(dbData);
33+
} catch (IllegalArgumentException e) {
34+
log.warn("잘못된 artist_type 값 발견: {}, null로 처리", dbData);
35+
return null;
36+
}
37+
}
38+
}
39+
40+

src/main/java/com/back/web7_9_codecrete_be/domain/artists/repository/ArtistLikeRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.back.web7_9_codecrete_be.domain.artists.repository;
22

3+
import com.back.web7_9_codecrete_be.domain.artists.dto.response.LikeArtistsResponse;
34
import com.back.web7_9_codecrete_be.domain.artists.entity.Artist;
45
import com.back.web7_9_codecrete_be.domain.artists.entity.ArtistLike;
56
import com.back.web7_9_codecrete_be.domain.users.entity.User;
@@ -23,4 +24,10 @@ public interface ArtistLikeRepository extends JpaRepository<ArtistLike, Long> {
2324
""")
2425
List<Long> findArtistIdsByUserId(@Param("userId") Long userId);
2526

27+
@Query("""
28+
select al.artist
29+
from ArtistLike al
30+
where al.user.id = :userId
31+
""")
32+
List<Artist> findLikeArtistsByUserId(@Param("userId") Long userId);
2633
}

src/main/java/com/back/web7_9_codecrete_be/domain/artists/repository/ArtistRepository.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ public interface ArtistRepository extends JpaRepository<Artist, Long> {
2323
boolean existsByArtistName(String artistName);
2424
boolean existsByNameKo(String nameKo);
2525

26-
List<Artist> findTop5ByArtistGroupAndIdNot(String artistGroup, long excludeId);
26+
@Query("SELECT a FROM Artist a WHERE a.artistGroup = :artistGroup AND a.id != :excludeId ORDER BY a.likeCount DESC, a.id ASC")
27+
List<Artist> findTop5ByArtistGroupAndIdNot(@org.springframework.data.repository.query.Param("artistGroup") String artistGroup,
28+
@org.springframework.data.repository.query.Param("excludeId") long excludeId);
2729

2830
@Query("""
2931
SELECT DISTINCT a FROM Artist a
3032
JOIN a.artistGenres ag
3133
WHERE ag.genre.id = :genreId AND a.id != :excludeId
32-
ORDER BY a.likeCount DESC
34+
ORDER BY a.likeCount DESC, a.id ASC
3335
""")
3436
List<Artist> findTop5ByGenreIdAndIdNot(@org.springframework.data.repository.query.Param("genreId") Long genreId,
3537
@org.springframework.data.repository.query.Param("excludeId") long excludeId,
@@ -57,4 +59,14 @@ List<Artist> findTop5ByGenreIdAndIdNot(@org.springframework.data.repository.quer
5759
// 배치 조회: spotifyId 리스트로 존재하는 아티스트의 spotifyId만 반환
5860
@Query("SELECT a.spotifyArtistId FROM Artist a WHERE a.spotifyArtistId IN :spotifyIds")
5961
List<String> findSpotifyIdsBySpotifyIdsIn(@org.springframework.data.repository.query.Param("spotifyIds") List<String> spotifyIds);
62+
63+
// 배치 조회: spotifyId 리스트로 존재하는 아티스트 전체 엔티티 반환 (Bulk 저장용)
64+
@Query("SELECT a FROM Artist a WHERE a.spotifyArtistId IN :spotifyIds")
65+
List<Artist> findBySpotifyArtistIdIn(@org.springframework.data.repository.query.Param("spotifyIds") List<String> spotifyIds);
66+
67+
// 같은 artistType인 아티스트들 조회 (관련 아티스트 추천용)
68+
@Query("SELECT a FROM Artist a WHERE a.artistType = :artistType AND a.id != :excludeId ORDER BY a.likeCount DESC, a.id ASC")
69+
List<Artist> findByArtistTypeAndIdNot(@org.springframework.data.repository.query.Param("artistType") com.back.web7_9_codecrete_be.domain.artists.entity.ArtistType artistType,
70+
@org.springframework.data.repository.query.Param("excludeId") long excludeId,
71+
Pageable pageable);
6072
}

src/main/java/com/back/web7_9_codecrete_be/domain/artists/repository/ConcertArtistRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import org.springframework.data.jpa.repository.JpaRepository;
55
import org.springframework.stereotype.Repository;
66

7+
import java.util.List;
8+
79
@Repository
810
public interface ConcertArtistRepository extends JpaRepository<ConcertArtist, Long> {
11+
List<ConcertArtist> getConcertArtistsByConcert_ConcertId(Long concertConcertId);
912
}

src/main/java/com/back/web7_9_codecrete_be/domain/artists/service/ArtistService.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.back.web7_9_codecrete_be.domain.artists.repository.ArtistRepository;
88
import com.back.web7_9_codecrete_be.domain.artists.repository.ArtistLikeRepository;
99
import com.back.web7_9_codecrete_be.domain.artists.repository.ConcertArtistRepository;
10+
import com.back.web7_9_codecrete_be.domain.artists.service.spotifyService.SpotifyService;
1011
import com.back.web7_9_codecrete_be.domain.concerts.entity.Concert;
1112
import com.back.web7_9_codecrete_be.domain.concerts.repository.ConcertRepository;
1213
import com.back.web7_9_codecrete_be.domain.concerts.service.ConcertService;
@@ -223,4 +224,12 @@ public LikeArtistResponse findArtistLikeByUserId(Artist artist, User user) {
223224
return new LikeArtistResponse(artistLikeRepository.existsByArtistAndUser(artist, user));
224225
}
225226

227+
@Transactional(readOnly = true)
228+
public List<LikeArtistsResponse> findLikeArtistsByUserid(User user) {
229+
List<Artist> likeArtists = artistLikeRepository.findLikeArtistsByUserId(user.getId());
230+
return likeArtists.stream()
231+
.map(LikeArtistsResponse::from)
232+
.toList();
233+
}
234+
226235
}

0 commit comments

Comments
 (0)