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

카페 이미지 Outer Join -> Inner Join (카페 이미지 최소 1개 이상 포함시키기) #492

Merged
merged 39 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f0d02b2
refactor:LikedCafeThumbnail dto명 변경
hum02 Sep 8, 2023
dd80429
chore:QueryDsl 의존성 및 환경설정(#433)
hum02 Sep 10, 2023
b4e29c1
feat:카페 동적 쿼리 repository구현(#433)
hum02 Sep 10, 2023
f86685e
feat:카페 검색 API 구현(#433)
hum02 Sep 10, 2023
1d74670
refactor:가독성 위한 개행
hum02 Sep 10, 2023
d294873
feat:검색 기준마다의 검색어로 카페 조회 기능(#433)
hum02 Sep 14, 2023
9e22d9f
refactor:cafeThumbnailResponse 메서드가 Cafe를 인자로 받도록 수정
hum02 Sep 14, 2023
dfb99f9
refactor:불필요한 서브쿼리 삭제(#433)
hum02 Sep 14, 2023
5f80dd5
refactor:querydsl 메서드에 distinct 추가(#433)
hum02 Sep 14, 2023
c18154a
refactor:불필요한 join과 distinct삭제
hum02 Sep 15, 2023
00185fa
임시 커밋 push 안됨
hum02 Sep 18, 2023
20c4c88
refactor:검색 기능 가독성 개선(#433)
hum02 Sep 19, 2023
2fab8e0
refactor:불필요한 파일 삭제
hum02 Sep 19, 2023
806b0f8
refactor:menu에 따른 분기처리 가독성 개선
hum02 Sep 20, 2023
c0f46c5
feat:검색 기능에 fulltext search 적용(#433)
hum02 Sep 25, 2023
022b301
Merge branch 'dev' into feat/433-search
hum02 Sep 25, 2023
c2d288b
Merge pull request #455 from woowacourse-teams/feat/451-map
green-kong Sep 25, 2023
89ccc35
Merge pull request #478 from woowacourse-teams/fix/477-remove-console…
solo5star Sep 25, 2023
3ad24e4
refactor:fulltext 인덱스 설정 sql문 컨벤션 수정(#433)
hum02 Sep 25, 2023
e8d3325
refactor:match against문 querydsl 가독성 개선(#433)
hum02 Sep 25, 2023
b6f77e7
Merge branch 'dev' into refactor/460-osiv
donghae-kim Sep 26, 2023
31a436a
Merge pull request #461 from woowacourse-teams/refactor/460-osiv
donghae-kim Sep 26, 2023
595cbba
Merge branch 'dev' into feat/433-search
hum02 Sep 26, 2023
0cbc612
feat: 테스트 때도 batch size 추가
nuyh99 Sep 20, 2023
cbbd7a4
feat: inner join으로 변경(nullable 객체 fetch join하기 위함)
nuyh99 Sep 20, 2023
53d9b09
feat: 컬렉션 타입 필드 null 방지
nuyh99 Sep 20, 2023
072f435
refactor: CafeRankGenerator -> Pageable의 offset 사용
nuyh99 Sep 20, 2023
fe8ef7f
feat: 카페 이미지 생성자 검증 기능 추가
nuyh99 Sep 20, 2023
33332c7
feat: UnviewedCafe와 Cafe outer 조인 -> inner 조인으로 변경
nuyh99 Sep 21, 2023
c4635fe
chore: 디폴트 설정 명시 제거
nuyh99 Sep 26, 2023
c8a063b
chore: 필요 없는 의존 제거
nuyh99 Sep 26, 2023
8642078
refactor: 필요한 부분만 fetch join 하도록 변경
nuyh99 Sep 26, 2023
cb81c57
Merge pull request #443 from woowacourse-teams/feat/433-search
hum02 Sep 26, 2023
3198e3a
chore: resolve merge conflict
nuyh99 Sep 26, 2023
6dcdd30
refactor: Cafe가 없는 Member는 어차피 left join해도 조회가 불가능하므로 inner join으로 변경
nuyh99 Sep 26, 2023
ff55c20
fix: pageSize를 endIndex로 처리하던 문제 해결
nuyh99 Sep 26, 2023
7a9543e
fix: 카페의 이미지가 없을 때 방어 로직 작성
nuyh99 Sep 26, 2023
9254bc8
fix: 멤버의 getLikedCafes 방어 로직 작성
nuyh99 Sep 26, 2023
f84fb29
chore: static import
nuyh99 Sep 26, 2023
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
20 changes: 20 additions & 0 deletions server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ dependencies {
//Flyway
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql'

//QueryDsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}

def generatedQueryDsl = 'build/generated/querydsl'

sourceSets {
main.java.srcDirs += [generatedQueryDsl]
}

tasks.withType(JavaCompile).configureEach {
options.getGeneratedSourceOutputDirectory().set(file(generatedQueryDsl))
}

clean.doLast {
file(generatedQueryDsl).deleteDir()
}

ext {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.project.yozmcafe.config;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QueryDslConfig {

@PersistenceContext
private EntityManager entityManager;

@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.project.yozmcafe.controller.dto.cafe.CafeRankResponse;
import com.project.yozmcafe.controller.dto.cafe.CafeResponse;
import com.project.yozmcafe.controller.dto.cafe.CafeSearchRequest;
import com.project.yozmcafe.controller.dto.cafe.CafeSearchResponse;
import com.project.yozmcafe.service.CafeService;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
Expand All @@ -17,8 +19,7 @@
@RequestMapping("/cafes")
public class CafeController {

private static final int PAGE_SIZE = 5;
private static final int RANKING_PAGE_SIZE = 10;
private static final int CAFE_PAGE_SIZE = 5;

private final CafeService cafeService;

Expand All @@ -28,27 +29,34 @@ public CafeController(final CafeService cafeService) {

@GetMapping
public ResponseEntity<List<CafeResponse>> getCafesForLoggedInMember(@LoginUser final String memberId) {
List<CafeResponse> cafeResponses = cafeService.getCafesForLoginMember(memberId, PAGE_SIZE);
final List<CafeResponse> cafeResponses = cafeService.getCafesForLoginMember(memberId, CAFE_PAGE_SIZE);
return ResponseEntity.ok(cafeResponses);
}

@GetMapping("/guest")
public ResponseEntity<List<CafeResponse>> getCafesForUnLoggedInMember(@PageableDefault(size = PAGE_SIZE) final Pageable pageable) {
List<CafeResponse> cafeResponses = cafeService.getCafesForUnLoginMember(pageable);
public ResponseEntity<List<CafeResponse>> getCafesForUnLoggedInMember(
@PageableDefault(size = CAFE_PAGE_SIZE) final Pageable pageable) {
final List<CafeResponse> cafeResponses = cafeService.getCafesForUnLoginMember(pageable);
return ResponseEntity.ok(cafeResponses);
}

@GetMapping("/ranks")
public ResponseEntity<List<CafeRankResponse>> getCafesOrderByLikeCount(@PageableDefault(size = RANKING_PAGE_SIZE) final Pageable pageable) {
public ResponseEntity<List<CafeRankResponse>> getCafesOrderByLikeCount(@PageableDefault final Pageable pageable) {
final List<CafeRankResponse> cafeRankResponses = cafeService.getCafesOrderByLikeCount(pageable);
return ResponseEntity.ok(cafeRankResponses);
}

@GetMapping("/{cafeId}")
public ResponseEntity<CafeResponse> getCafeById(@PathVariable("cafeId") final long cafeId) {
CafeResponse cafeResponse = cafeService.getCafeById(cafeId);
final CafeResponse cafeResponse = cafeService.getCafeByIdOrThrow(cafeId);
return ResponseEntity.ok(cafeResponse);
}

@GetMapping("/search")
public ResponseEntity<List<CafeSearchResponse>> getCafeBySearch(final CafeSearchRequest cafeSearchRequest) {
final List<CafeSearchResponse> cafeSearchResponses = cafeService.getCafesBySearch(cafeSearchRequest);
return ResponseEntity.ok(cafeSearchResponses);
}
}


Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.project.yozmcafe.controller;

import com.project.yozmcafe.controller.dto.cafe.CafeThumbnailResponse;
import com.project.yozmcafe.controller.dto.cafe.LikedCafeResponse;
import com.project.yozmcafe.controller.dto.cafe.LikedCafeThumbnailResponse;
import com.project.yozmcafe.service.LikedCafeService;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
Expand All @@ -26,9 +26,9 @@ public LikedCafeController(final LikedCafeService likedCafeService) {
}

@GetMapping("/members/{memberId}/liked-cafes")
public ResponseEntity<List<LikedCafeThumbnailResponse>> getLikedCafeThumbnails(@PathVariable("memberId") final String memberId,
@PageableDefault(size = PAGE_SIZE) final Pageable pageable) {
final List<LikedCafeThumbnailResponse> likedCafes = likedCafeService.findLikedCafeThumbnailsByMemberId(memberId, pageable);
public ResponseEntity<List<CafeThumbnailResponse>> getLikedCafeThumbnails(@PathVariable("memberId") final String memberId,
@PageableDefault(size = PAGE_SIZE) final Pageable pageable) {
final List<CafeThumbnailResponse> likedCafes = likedCafeService.findLikedCafeThumbnailsByMemberId(memberId, pageable);

return ResponseEntity.ok(likedCafes);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.project.yozmcafe.controller.dto.cafe;

public record CafeSearchRequest(String cafeName, String menu, String address) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.project.yozmcafe.controller.dto.cafe;

import com.project.yozmcafe.domain.cafe.Cafe;

public record CafeSearchResponse(Long id, String name, String address, String image, int likeCount) {
public static CafeSearchResponse from(final Cafe cafe) {
return new CafeSearchResponse(
cafe.getId(),
cafe.getName(),
cafe.getAddress(),
cafe.getRepresentativeImage(),
cafe.getLikeCount()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.project.yozmcafe.controller.dto.cafe;

import com.project.yozmcafe.domain.cafe.Cafe;

public record CafeThumbnailResponse(Long cafeId, String imageUrl) {

public static CafeThumbnailResponse from(final Cafe cafe) {
return new CafeThumbnailResponse(cafe.getId(), cafe.getRepresentativeImage());
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package com.project.yozmcafe.domain.cafe;

import com.project.yozmcafe.exception.BadRequestException;
import jakarta.persistence.*;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

import java.util.Objects;

Expand Down Expand Up @@ -71,7 +76,7 @@ private void validate(final String name, final String address, final Images imag
}
}

public Cafe(String name, String address, Images images, Detail detail) {
public Cafe(final String name, final String address, final Images images, final Detail detail) {
this(null, name, address, images, detail, 0);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.project.yozmcafe.domain.cafe;

import java.util.List;

public interface CafeCustomRepository {

List<Cafe> findAllBy(final String cafeName, final String menu, final String address);

List<Cafe> findAllBy(final String cafeName, final String address);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.project.yozmcafe.domain.cafe;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.StringPath;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import org.springframework.stereotype.Repository;

import java.util.List;

import static com.project.yozmcafe.domain.cafe.QCafe.cafe;
import static com.project.yozmcafe.domain.menu.QMenu.menu;
import static com.querydsl.core.types.dsl.Expressions.numberTemplate;
import static io.micrometer.common.util.StringUtils.isBlank;

@Repository
public class CafeCustomRepositoryImpl extends QuerydslRepositorySupport implements CafeCustomRepository {

private static final double MATCH_THRESHOLD = 0.0;

public CafeCustomRepositoryImpl() {
super(Cafe.class);
}

public List<Cafe> findAllBy(final String cafeNameWord, final String menuWord, final String addressWord) {
return from(cafe)
.innerJoin(menu).on(menu.cafe.eq(cafe))
.where(
contains(cafe.name, cafeNameWord),
contains(menu.name, menuWord),
contains(cafe.address, addressWord))
.fetch();
}

public List<Cafe> findAllBy(final String cafeNameWord, final String addressWord) {
return from(cafe)
.where(
contains(cafe.name, cafeNameWord),
contains(cafe.address, addressWord))
.fetch();
}

private BooleanExpression contains(final StringPath target, final String searchWord) {
if (isBlank(searchWord)) {
return null;
}

final String formattedSearchWord = "\"" + searchWord + "\"";
return numberTemplate(Double.class, "function('match_against', {0}, {1})",
target, formattedSearchWord)
.gt(MATCH_THRESHOLD);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,30 @@
import java.util.List;
import java.util.Optional;

public interface CafeRepository extends JpaRepository<Cafe, Long> {
public interface CafeRepository extends JpaRepository<Cafe, Long>, CafeCustomRepository {

Slice<Cafe> findSliceBy(Pageable pageable);

@Override
@Query("""
select c
from Cafe c
left join fetch c.images.urls
where c.id = :cafeId
SELECT c
FROM Cafe c
JOIN FETCH c.images.urls
WHERE c.id = :cafeId
""")
Optional<Cafe> findById(@Param("cafeId") Long cafeId);

@Override
@Query("""
select c
from Cafe c
left join fetch c.images.urls
SELECT c
FROM Cafe c
JOIN FETCH c.images.urls
""")
List<Cafe> findAll();

@Query("""
SELECT c.id
FROM Cafe c
SELECT c.id
FROM Cafe c
ORDER BY c.likeCount DESC
""")
List<Long> findCafeIdsOrderByLikeCount(Pageable pageable);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.project.yozmcafe.domain.cafe;

import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.FunctionContributor;

import static org.hibernate.type.StandardBasicTypes.DOUBLE;

public class CustomFunctionContributor implements FunctionContributor {

private static final String FUNCTION_NAME = "match_against";
private static final String FUNCTION_PATTERN = "match (?1) against (?2 in boolean mode)";

@Override
public void contributeFunctions(final FunctionContributions functionContributions) {
functionContributions.getFunctionRegistry()
.registerPattern(FUNCTION_NAME, FUNCTION_PATTERN,
functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(DOUBLE));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Embeddable;
import jakarta.persistence.FetchType;

import java.util.ArrayList;
import java.util.List;

import static com.project.yozmcafe.exception.ErrorCode.DUPLICATED_CAFE_AVAILABLE_TIMES;
Expand All @@ -21,8 +21,8 @@ public class Detail {
public static final int MAP_URL_MAX_LENGTH = 512;
public static final int PHONE_MAX_LENGTH = 20;

@ElementCollection(fetch = FetchType.LAZY)
private List<AvailableTime> availableTimes;
@ElementCollection
private List<AvailableTime> availableTimes = new ArrayList<>();
@Column(nullable = false)
private String mapUrl;
@Column(columnDefinition = "text")
Expand Down
Loading