Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] feat: Club 페이징 적용 및 batch size 설정 #622

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6abbe66
chore: local 환경 batch_fetch_size 설정 추가
J-I-H-O Sep 26, 2024
8f5605e
test: 단건 조회 테스트 추가
J-I-H-O Sep 26, 2024
3f1fa1c
refactor: ClubPet 엔티티만 fetch join 하도록 수정
J-I-H-O Oct 3, 2024
d71cb20
refactor: elementalCollection 엔티티로 승격
J-I-H-O Oct 3, 2024
29edf1e
refactor: 불필요한 정렬문 제거
J-I-H-O Oct 3, 2024
c6b582a
refactor: Criteria 및 join문 제거
J-I-H-O Oct 3, 2024
171e2d2
refactor: 불필요한 조건문 제거
J-I-H-O Oct 4, 2024
b659fff
feat: 페이징 구현
J-I-H-O Oct 4, 2024
4675df1
refactor: 항상 지정된 size 만큼 응답하도록 수정
J-I-H-O Oct 4, 2024
925df3b
refactor: 필요한 페이징 정보만 응답하도록 DTO 생성
J-I-H-O Oct 7, 2024
b215f8f
refactor: 클라이언트로부터 페이지 사이즈를 입력받도록 변경
J-I-H-O Oct 7, 2024
8f3b1c6
test: 페이징 테스트 추가
J-I-H-O Oct 7, 2024
c7eb13d
refactor: 메서드 분리
J-I-H-O Oct 7, 2024
eb1c84a
test: 페이지 사이즈에 따른 추가 쿼리 테스트
J-I-H-O Oct 7, 2024
c28300d
Merge branch 'develop' into refactor/batch-size
J-I-H-O Oct 7, 2024
9c108e8
chore: dev 및 prod 환경 batch size 옵션 추가
J-I-H-O Oct 7, 2024
d3748e5
refactor: 모임 필터링 request DTO 필드 nullable 하도록 변경
J-I-H-O Oct 7, 2024
f6f2d0a
fix: 버전 대응을 위해 nullable 처리
J-I-H-O Oct 11, 2024
6ef57a3
fix: 래퍼 타입을 원시 타입으로 언박싱 하면서 발생하는 NPE 해결
J-I-H-O Oct 11, 2024
446c230
fix: 래퍼 타입을 원시 타입으로 언박싱 하면서 발생하는 NPE 해결2
J-I-H-O Oct 11, 2024
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 @@ -4,6 +4,7 @@
import com.happy.friendogly.pet.domain.Gender;
import com.happy.friendogly.pet.domain.SizeType;
import java.util.Set;
import java.util.stream.Collectors;

public record FindClubDetailsResponse(
Long clubId,
Expand All @@ -13,6 +14,15 @@ public record FindClubDetailsResponse(
) {

public FindClubDetailsResponse(Long myMemberId, Club club) {
this(club.getId(), myMemberId, club.getAllowedSizes(), club.getAllowedGenders());
this(
club.getId(),
myMemberId,
club.getAllowedSizes().stream()
.map(clubSize -> clubSize.getClubSizeId().getAllowedSize())
.collect(Collectors.toSet()),
club.getAllowedGenders().stream()
.map(clubGender -> clubGender.getClubGenderId().getAllowedGender())
.collect(Collectors.toSet())
Comment on lines +20 to +25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 List -> Set으로 바꾸는거죠? 한 줄로 될 것 같아요!

);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import com.happy.friendogly.club.dto.request.SaveClubMemberRequest;
import com.happy.friendogly.club.dto.request.SaveClubRequest;
import com.happy.friendogly.club.dto.request.UpdateClubRequest;
import com.happy.friendogly.club.dto.response.FindClubByFilterResponse;
import com.happy.friendogly.club.dto.response.FindClubOwningResponse;
import com.happy.friendogly.club.dto.response.FindClubPageByFilterResponse;
import com.happy.friendogly.club.dto.response.FindClubParticipatingResponse;
import com.happy.friendogly.club.dto.response.FindClubResponse;
import com.happy.friendogly.club.dto.response.SaveClubMemberResponse;
Expand Down Expand Up @@ -49,7 +49,7 @@ public ApiResponse<FindClubResponse> findById(@Auth Long memberId, @PathVariable
}

@GetMapping("/searching")
public ApiResponse<List<FindClubByFilterResponse>> findByFilter(
public ApiResponse<FindClubPageByFilterResponse> findByFilter(
@Auth Long memberId,
@Valid @ModelAttribute FindClubByFilterRequest request
) {
Comment on lines 51 to 55
Copy link
Contributor

@takoyakimchi takoyakimchi Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이전 버전 앱 사용자는 명세가 바뀌면서 예외가 터질 수도 있을 것 같아요.
단순히 기존 명세에서 필드가 추가만 되었다고 하더라도 예측이 쉽지만은 않을 것 같아요.
버저닝 하는 건 어떨까요?

Expand Down Expand Up @@ -105,5 +105,4 @@ public ResponseEntity<ApiResponse<UpdateClubResponse>> update(
UpdateClubResponse response = clubCommandService.update(clubId, memberId, request);
return ResponseEntity.ok(ApiResponse.ofSuccess(response));
}

}
53 changes: 18 additions & 35 deletions backend/src/main/java/com/happy/friendogly/club/domain/Club.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
import com.happy.friendogly.pet.domain.Pet;
import com.happy.friendogly.pet.domain.SizeType;
import jakarta.persistence.CascadeType;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
Expand All @@ -19,15 +17,12 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.NamedAttributeNode;
import jakarta.persistence.NamedEntityGraph;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.OrderBy;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.AccessLevel;
Expand All @@ -36,15 +31,6 @@
import lombok.NoArgsConstructor;

@Entity
@NamedEntityGraph(
name = "graph.Club",
attributeNodes = {
@NamedAttributeNode("clubMembers"),
@NamedAttributeNode("clubPets"),
@NamedAttributeNode("allowedSizes"),
@NamedAttributeNode("allowedGenders"),
}
)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Club {
Expand All @@ -62,18 +48,6 @@ public class Club {
@Embedded
private MemberCapacity memberCapacity;

@ElementCollection
@Enumerated(EnumType.STRING)
@CollectionTable(name = "club_gender", joinColumns = @JoinColumn(name = "club_id"))
@Column(name = "allowed_gender", nullable = false)
private Set<Gender> allowedGenders;

@ElementCollection
@Enumerated(EnumType.STRING)
@CollectionTable(name = "club_size", joinColumns = @JoinColumn(name = "club_id"))
@Column(name = "allowed_size", nullable = false)
private Set<SizeType> allowedSizes;

@Embedded
private Address address;

Expand All @@ -87,13 +61,18 @@ public class Club {
@Column(name = "status", nullable = false)
private Status status;

@OneToMany(mappedBy = "clubGenderId.club", orphanRemoval = true, cascade = CascadeType.ALL)
private List<ClubGender> allowedGenders = new ArrayList<>();

@OneToMany(mappedBy = "clubSizeId.club", orphanRemoval = true, cascade = CascadeType.ALL)
private List<ClubSize> allowedSizes = new ArrayList<>();

@OneToMany(mappedBy = "clubMemberId.club", orphanRemoval = true, cascade = CascadeType.ALL)
@OrderBy("createdAt")
private Set<ClubMember> clubMembers = new HashSet<>();
private List<ClubMember> clubMembers = new ArrayList<>();

@OneToMany(mappedBy = "clubPetId.club", orphanRemoval = true, cascade = CascadeType.ALL)
@OrderBy
private Set<ClubPet> clubPets = new HashSet<>();
private List<ClubPet> clubPets = new ArrayList<>();

@OneToOne(fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.ALL)
private ChatRoom chatRoom;
Expand All @@ -117,8 +96,8 @@ private Club(
this.content = new Content(content);
this.address = new Address(province, city, village);
this.memberCapacity = new MemberCapacity(memberCapacity);
this.allowedGenders = allowedGenders;
this.allowedSizes = allowedSizes;
this.allowedGenders = allowedGenders.stream().map(gender -> new ClubGender(this, gender)).toList();
this.allowedSizes = allowedSizes.stream().map(sizeType -> new ClubSize(this, sizeType)).toList();
Comment on lines +99 to +100
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기도 stream까지 필요없을 것 같아요

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map때문에 stream한 것 같은데 다른 방법이 있나요??

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗 맞네요 ㅋㅋ

this.imageUrl = imageUrl;
this.status = status;
this.createdAt = createdAt;
Expand Down Expand Up @@ -209,15 +188,19 @@ private void validateParticipatePet(Pet pet) {
}

private boolean canJoinWith(Pet pet) {
return allowedGenders.contains(pet.getGender()) && allowedSizes.contains(pet.getSizeType());
boolean isGenderMatch = allowedGenders.stream()
.anyMatch(clubGender -> clubGender.isSameGenderWith(pet.getGender()));
boolean isSizeMatch = allowedSizes.stream()
.anyMatch(clubSize -> clubSize.isSameSizeWith(pet.getSizeType()));

return isGenderMatch && isSizeMatch;
}

public boolean isJoinable(Member member, List<Pet> pets) {
boolean hasJoinablePet = pets.stream()
.anyMatch(this::canJoinWith);
boolean isNotFull = !this.memberCapacity.isCapacityReached(countClubMember());

return hasJoinablePet && isNotFull && !isAlreadyJoined(member) && isOpen();
return hasJoinablePet && !isAlreadyJoined(member) && isOpen();
Comment on lines -218 to +203
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isOpen에 isNotFull이 포함이군요 ~!!

}

public void removeClubMember(Member member) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.happy.friendogly.club.domain;

import com.happy.friendogly.exception.FriendoglyException;
import com.happy.friendogly.pet.domain.Gender;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class ClubGender {

@EmbeddedId
private ClubGenderId clubGenderId;

public ClubGender(Club club, Gender gender) {
validateClub(club);
validateGender(gender);
this.clubGenderId = new ClubGenderId(club, gender);
}

private void validateClub(Club club) {
if (club == null) {
throw new FriendoglyException("모임 정보는 필수입니다.");
}
}

private void validateGender(Gender gender) {
if (gender == null) {
throw new FriendoglyException("모임에 참여하는 반려견의 성별 정보는 필수입니다.");
}
}

public boolean isSameGenderWith(Gender gender) {
return this.getClubGenderId().getAllowedGender() == gender;
}
Comment on lines +37 to +39
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public boolean isSameGenderWith(Gender gender) {
return this.getClubGenderId().getAllowedGender() == gender;
}
public boolean hasGender(Gender gender) {
return this.getClubGenderId().getAllowedGender() == gender;
}

이름 제안해봅니당

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.happy.friendogly.club.domain;

import com.happy.friendogly.pet.domain.Gender;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import java.io.Serializable;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@EqualsAndHashCode
public class ClubGenderId implements Serializable {

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

@Enumerated(EnumType.STRING)
private Gender allowedGender;

public ClubGenderId(Club club, Gender allowedGender) {
this.club = club;
this.allowedGender = allowedGender;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public ClubPet(Club club, Pet pet) {

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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.happy.friendogly.club.domain;

import com.happy.friendogly.exception.FriendoglyException;
import com.happy.friendogly.pet.domain.SizeType;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class ClubSize {

@EmbeddedId
private ClubSizeId clubSizeId;

public ClubSize(Club club, SizeType sizeType) {
validateClub(club);
validateSizeType(sizeType);
this.clubSizeId = new ClubSizeId(club, sizeType);
}

private void validateClub(Club club) {
if (club == null) {
throw new FriendoglyException("모임 정보는 필수입니다.");
}
}

private void validateSizeType(SizeType sizeType) {
if (sizeType == null) {
throw new FriendoglyException("모임에 참여하는 반려견의 크기 정보는 필수입니다.");
}
}

public boolean isSameSizeWith(SizeType sizeType) {
return this.getClubSizeId().getAllowedSize() == sizeType;
}
Comment on lines +37 to +39
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public boolean isSameSizeWith(SizeType sizeType) {
return this.getClubSizeId().getAllowedSize() == sizeType;
}
public boolean hasSizeType(SizeType sizeType) {
return this.getClubSizeId().getAllowedSize() == sizeType;
}

제안

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.happy.friendogly.club.domain;

import com.happy.friendogly.pet.domain.SizeType;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import java.io.Serializable;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@EqualsAndHashCode
public class ClubSizeId implements Serializable {

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

@Enumerated(EnumType.STRING)
private SizeType allowedSize;

public ClubSizeId(Club club, SizeType allowedSize) {
this.club = club;
this.allowedSize = allowedSize;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import java.time.LocalDateTime;
import java.util.Set;

public record FindClubByFilterRequest(
Expand All @@ -19,7 +20,20 @@ public record FindClubByFilterRequest(
Set<String> genderParams,

@NotEmpty(message = "반려견 크기 검색 조건은 필수입니다.")
Set<String> sizeParams
Set<String> sizeParams,

/**
* TODO: 일단 nullable 하게 변경.
* 안드로이드 페이징 코드 머지됐을 때 non-nullable하게 바꾸기 (일부러 타입도 wrapper 타입으로 변경해둠)
*/
// @Positive(message = "페이지 사이즈는 1 이상의 정수 입니다.")
Integer pageSize,

// @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
LocalDateTime lastFoundCreatedAt,

// @PositiveOrZero(message = "마지막으로 조회한 모임 ID는 0 이상의 정수 입니다.")
Long lastFoundId
) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public record FindClubByFilterResponse(
Long id,
Expand All @@ -22,7 +23,6 @@ public record FindClubByFilterResponse(
int currentMemberCount,
String imageUrl,
List<String> petImageUrls

) {

public FindClubByFilterResponse(
Expand All @@ -37,8 +37,12 @@ public FindClubByFilterResponse(
new AddressDetailResponse(club.getAddress()),
club.getStatus(),
club.getCreatedAt(),
club.getAllowedGenders(),
club.getAllowedSizes(),
club.getAllowedGenders().stream()
.map(clubGender -> clubGender.getClubGenderId().getAllowedGender())
.collect(Collectors.toSet()),
club.getAllowedSizes().stream()
.map(clubSize -> clubSize.getClubSizeId().getAllowedSize())
.collect(Collectors.toSet()),
club.getMemberCapacity().getValue(),
club.countClubMember(),
club.getImageUrl(),
Expand Down
Loading
Loading