Skip to content

Commit

Permalink
[BE] refactor: Club 매핑 테이블 엔티티 연관 관계 개선 (#165)
Browse files Browse the repository at this point in the history
  • Loading branch information
jimi567 authored Jul 22, 2024
1 parent 0a2645c commit 7ad8054
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@

import com.woowacourse.friendogly.exception.FriendoglyException;
import com.woowacourse.friendogly.member.domain.Member;
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.ManyToOne;
import jakarta.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -35,9 +31,6 @@ public class ClubMember {
@JoinColumn(name = "member_id", nullable = false)
private Member member;

@OneToMany(mappedBy = "clubMember", orphanRemoval = true, cascade = CascadeType.ALL)
private List<ClubMemberPet> clubMemberPets = new ArrayList<>();

@Builder
public ClubMember(Club club, Member member) {
validateClub(club);
Expand All @@ -57,17 +50,4 @@ private void validateMember(Member member) {
throw new FriendoglyException("모임에 참여하는 회원 정보는 필수입니다.");
}
}

public void addClubMemberPets(ClubMemberPet pet) {
//TODO : 데려갈 수 있는 최대 반려견이 정해지면 예외처리
//TODO : 해당 팻이 member가 키우는 팻인지 검증
clubMemberPets.add(pet);
}

public String findOverviewPetImage() {
if (clubMemberPets.isEmpty()) {
return null;
}
return clubMemberPets.get(0).getPet().getImageUrl().getValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,30 @@
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class ClubMemberPet {
public class ClubPet {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "club_member_id", nullable = false)
private ClubMember clubMember;
@JoinColumn(name = "club_id", nullable = false)
private Club club;

@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "pet_id", nullable = false)
private Pet pet;

@Builder
public ClubMemberPet(ClubMember clubMember, Pet pet) {
validateClubMember(clubMember);
public ClubPet(Club club, Pet pet) {
validateClub(club);
validatePet(pet);
this.clubMember = clubMember;
this.club = club;
this.pet = pet;
}

private void validateClubMember(ClubMember clubMember) {
if (clubMember == null) {
private void validateClub(Club club) {
if (club == null) {
throw new FriendoglyException("모임에 참여하는 회원 정보는 필수입니다.");
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.woowacourse.friendogly.club.repository;

import com.woowacourse.friendogly.club.domain.ClubPet;
import java.util.List;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ClubPetRepository extends JpaRepository<ClubPet, Long> {

@EntityGraph(attributePaths = {"club", "pet"})
List<ClubPet> findAllByClubId(Long id);
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package com.woowacourse.friendogly.club.service;

import static java.util.stream.Collectors.toList;

import com.woowacourse.friendogly.club.domain.Club;
import com.woowacourse.friendogly.club.domain.ClubMember;
import com.woowacourse.friendogly.club.domain.ClubPet;
import com.woowacourse.friendogly.club.dto.request.FindSearchingClubRequest;
import com.woowacourse.friendogly.club.dto.response.FindSearchingClubResponse;
import com.woowacourse.friendogly.club.repository.ClubMemberPetRepository;
import com.woowacourse.friendogly.club.repository.ClubMemberRepository;
import com.woowacourse.friendogly.club.repository.ClubPetRepository;
import com.woowacourse.friendogly.club.repository.ClubRepository;
import com.woowacourse.friendogly.club.repository.ClubSpecification;
import com.woowacourse.friendogly.pet.domain.Pet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -19,16 +24,16 @@ public class ClubQueryService {

private final ClubRepository clubRepository;
private final ClubMemberRepository clubMemberRepository;
private final ClubMemberPetRepository clubMemberPetRepository;
private final ClubPetRepository clubPetRepository;

public ClubQueryService(
ClubRepository clubRepository,
ClubMemberRepository clubMemberRepository,
ClubMemberPetRepository clubMemberPetRepository
ClubPetRepository clubPetRepository
) {
this.clubRepository = clubRepository;
this.clubMemberRepository = clubMemberRepository;
this.clubMemberPetRepository = clubMemberPetRepository;
this.clubPetRepository = clubPetRepository;
}

public List<FindSearchingClubResponse> findSearching(FindSearchingClubRequest request) {
Expand All @@ -39,18 +44,23 @@ public List<FindSearchingClubResponse> findSearching(FindSearchingClubRequest re
.build();

return clubRepository.findAll(spec).stream()
.map(club -> {
List<String> overviewPetImages = clubMemberRepository.findAllByClubId(club.getId()).stream()
.map(ClubMember::findOverviewPetImage)
.toList();
return new FindSearchingClubResponse(
club,
clubMemberRepository.countByClubId(club.getId()),
overviewPetImages
);
})
.map(club -> new FindSearchingClubResponse(
club,
clubMemberRepository.countByClubId(club.getId()),
collectOverviewPetImages(club)
))
.toList();
}

private List<String> collectOverviewPetImages(Club club) {
Map<Long, List<Pet>> groupPetsByMemberId = clubPetRepository.findAllByClubId(club.getId()).stream()
.map(ClubPet::getPet)
.collect(Collectors.groupingBy(pet -> pet.getMember().getId()));

return groupPetsByMemberId.values().stream()
.map(petList -> petList.get(0).getImageUrl().getValue())
.collect(toList());
}
}


Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.woowacourse.friendogly.club.domain;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

Expand Down Expand Up @@ -74,31 +73,4 @@ void create_FailNullMember() {
.isInstanceOf(FriendoglyException.class)
.hasMessage("모임에 참여하는 회원 정보는 필수입니다.");
}

@DisplayName("리스트업에 나오는 참여 강아지 사진을 반환한다.")
@Test
void findClubOverviewPetImage() {
ClubMember clubMember = ClubMember.builder()
.club(club)
.member(member)
.build();

clubMember.addClubMemberPets(ClubMemberPet.builder()
.clubMember(clubMember)
.pet(pet)
.build());

assertThat(clubMember.findOverviewPetImage()).isEqualTo(pet.getImageUrl().getValue());
}

@DisplayName("참여 중인 회원이 어떤 강아지도 데리고 가지 않는다면 null을 반환한다.")
@Test
void findClubOverviewPetImage_FailNonPets() {
ClubMember clubMember = ClubMember.builder()
.club(club)
.member(member)
.build();

assertThat(clubMember.findOverviewPetImage()).isNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ class ClubQueryServiceTest extends ClubServiceTest {
@DisplayName("필터링된 모임을 정보를 조회한다.")
@Test
void findSearching() {
//서울특별시 송파구 신청동, (암컷, 중성화 암컷), 크기는 소형견이 조건인 club
Club club = saveNewClub();
Club club = getSavedClub(Set.of(Gender.FEMALE, Gender.FEMALE_NEUTERED), Set.of(SizeType.SMALL));

FindSearchingClubRequest request = new FindSearchingClubRequest(
address,
Expand Down Expand Up @@ -54,4 +53,20 @@ void findSearching() {
() -> assertThat(actual.petImageUrls()).containsExactlyInAnyOrderElementsOf(expected.petImageUrls())
);
}

@DisplayName("필터링된 모임을 정보가 없으면 빈 리스트를 반환한다.")
@Test
void findSearching_Nothing() {
Club club = getSavedClub(Set.of(Gender.FEMALE, Gender.FEMALE_NEUTERED), Set.of(SizeType.SMALL));

FindSearchingClubRequest request = new FindSearchingClubRequest(
address,
Set.of(Gender.MALE),
Set.of(SizeType.SMALL)
);

List<FindSearchingClubResponse> responses = clubQueryService.findSearching(request);

assertThat(responses.isEmpty()).isTrue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.woowacourse.friendogly.club.domain.Club;
import com.woowacourse.friendogly.club.domain.ClubMember;
import com.woowacourse.friendogly.club.domain.ClubMemberPet;
import com.woowacourse.friendogly.club.domain.ClubPet;
import com.woowacourse.friendogly.member.domain.Member;
import com.woowacourse.friendogly.pet.domain.Gender;
import com.woowacourse.friendogly.pet.domain.Pet;
Expand Down Expand Up @@ -33,31 +33,32 @@ public abstract class ClubServiceTest extends ServiceTest {
.sizeType(SizeType.SMALL)
.build();

private final Club club = Club.create(
"강아지 산책시키실 분 모아요.",
"매주 주말에 정기적으로 산책 모임하실분만",
address,
5,
member,
allowedGenders,
allowedSizes,
"https://image.com");

protected Club saveNewClub() {
protected Club getSavedClub(Set<Gender> genders, Set<SizeType> sizes) {
memberRepository.save(member);
petRepository.save(pet);

Club club = Club.create(
"강아지 산책시키실 분 모아요.",
"매주 주말에 정기적으로 산책 모임하실분만",
address,
5,
member,
genders,
sizes,
"https://image.com");

Club savedClub = clubRepository.save(club);
ClubMember clubMember = ClubMember.builder()
.member(member)
.club(club)
.build();

ClubMemberPet clubMemberPet = ClubMemberPet.builder()
.clubMember(clubMember)
ClubPet clubPet = ClubPet.builder()
.club(club)
.pet(pet)
.build();
clubMemberRepository.save(clubMember);
clubMemberPetRepository.save(clubMemberPet);
clubPetRepository.save(clubPet);

return savedClub;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.woowacourse.friendogly.support;

import com.woowacourse.friendogly.club.repository.ClubMemberPetRepository;
import com.woowacourse.friendogly.club.repository.ClubMemberRepository;
import com.woowacourse.friendogly.club.repository.ClubPetRepository;
import com.woowacourse.friendogly.club.repository.ClubRepository;
import com.woowacourse.friendogly.footprint.repository.FootprintRepository;
import com.woowacourse.friendogly.member.repository.MemberRepository;
Expand All @@ -20,7 +20,7 @@ public abstract class ServiceTest {
protected ClubMemberRepository clubMemberRepository;

@Autowired
protected ClubMemberPetRepository clubMemberPetRepository;
protected ClubPetRepository clubPetRepository;

@Autowired
protected MemberRepository memberRepository;
Expand All @@ -34,7 +34,7 @@ public abstract class ServiceTest {
@BeforeEach
void clearDB() {
clubMemberRepository.deleteAll();
clubMemberPetRepository.deleteAll();
clubPetRepository.deleteAll();
clubRepository.deleteAll();
footprintRepository.deleteAll();
petRepository.deleteAll();
Expand Down

0 comments on commit 7ad8054

Please sign in to comment.