Skip to content

Commit

Permalink
태그 목록 검색 기능 리팩터링 (#637)
Browse files Browse the repository at this point in the history
* refactor: 입력된 문자열로 태그 목록 검색 기능 리팩터링

* refactor: TagQueryService 태그 목록 검색 기능 리팩터링

* chore: 러너 게시글 태그 패키지 이동

* refactor: TagQueryController 태그 목록 검색 기능 리팩터링

* test: 인수 테스트 검증용 TestTagQueryRepository 수정

* refactor: 태그 목록 검색 조건인 TagReducedName 이 null 이거나 공백일 경우 빈 목록을 서비스 계층에서 반환하도록 수정
  • Loading branch information
hyena0608 authored Oct 11, 2023
1 parent 20dd808 commit 5bcaebd
Show file tree
Hide file tree
Showing 25 changed files with 357 additions and 359 deletions.
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
package touch.baton.domain.tag.command.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import touch.baton.domain.common.vo.TagName;
import touch.baton.domain.tag.command.Tag;
import touch.baton.domain.tag.command.vo.TagReducedName;

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

public interface TagCommandRepository extends JpaRepository<Tag, Long> {

Optional<Tag> findByTagName(final TagName tagName);

@Query("""
select t
from Tag t
where t.tagReducedName like :tagReducedName%
order by t.tagReducedName asc
limit 10
""")
List<Tag> readTagsByReducedName(@Param("tagReducedName") TagReducedName tagReducedName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import touch.baton.domain.tag.query.controller.response.TagSearchResponse;
import touch.baton.domain.tag.command.Tag;
import touch.baton.domain.tag.command.vo.TagReducedName;
import touch.baton.domain.tag.query.controller.response.TagSearchResponses;
import touch.baton.domain.tag.query.service.TagQueryService;

import java.util.Collections;
import java.util.List;

@RequiredArgsConstructor
Expand All @@ -23,14 +23,9 @@ public class TagQueryController {

@GetMapping("/search")
public ResponseEntity<TagSearchResponses.Detail> readTagsByTagName(@Nullable @RequestParam(required = false) final String tagName) {
if (tagName == null || tagName.isBlank()) {
return ResponseEntity.ok().body(TagSearchResponses.Detail.from(Collections.emptyList()));
}
final TagReducedName tagReducedName = TagReducedName.nullableInstance(tagName);
final List<Tag> foundTags = tagQueryService.readTagsByReducedName(tagReducedName, 10);

final List<TagSearchResponse.TagResponse> tagSearchResponses = tagQueryService.readTagsByReducedName(tagName).stream()
.map(TagSearchResponse.TagResponse::from)
.toList();

return ResponseEntity.ok(TagSearchResponses.Detail.from(tagSearchResponses));
return ResponseEntity.ok(TagSearchResponses.Detail.from(foundTags));
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package touch.baton.domain.tag.query.controller.response;

import touch.baton.domain.tag.command.Tag;

import java.util.List;

public record TagSearchResponses() {

public record Detail(List<TagSearchResponse.TagResponse> data) {
public static Detail from(final List<TagSearchResponse.TagResponse> data) {
return new Detail(data);

public static Detail from(final List<Tag> tags) {
final List<TagSearchResponse.TagResponse> response = tags.stream()
.map(TagSearchResponse.TagResponse::from)
.toList();

return new Detail(response);
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package touch.baton.domain.tag.query.repository;

import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import touch.baton.domain.tag.command.Tag;
import touch.baton.domain.tag.command.vo.TagReducedName;

import java.util.List;

import static touch.baton.domain.tag.command.QTag.tag;

@RequiredArgsConstructor
@Repository
public class TagQuerydslRepository {

private final JPAQueryFactory queryFactory;

public List<Tag> findByTagReducedName(final TagReducedName tagReducedName, final int limit) {
return queryFactory.selectFrom(tag)
.where(tag.tagReducedName.value.startsWith(tagReducedName.getValue()))
.orderBy(tag.tagReducedName.value.asc(), tag.tagName.value.desc())
.limit(limit)
.fetch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@
import org.springframework.transaction.annotation.Transactional;
import touch.baton.domain.tag.command.Tag;
import touch.baton.domain.tag.command.vo.TagReducedName;
import touch.baton.domain.tag.query.repository.TagQueryRepository;
import touch.baton.domain.tag.query.repository.TagQuerydslRepository;

import java.util.Collections;
import java.util.List;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class TagQueryService {

private final TagQueryRepository tagQueryRepository;
private final TagQuerydslRepository tagQuerydslRepository;

public List<Tag> readTagsByReducedName(final String tagName) {
return tagQueryRepository.readTagsByReducedName(TagReducedName.from(tagName));
public List<Tag> readTagsByReducedName(final TagReducedName tagReducedName, final int limit) {
if (tagReducedName == null || tagReducedName.getValue().isBlank()) {
return Collections.emptyList();
}

return tagQuerydslRepository.findByTagReducedName(tagReducedName, limit);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package touch.baton.assure.repository;

import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.stereotype.Repository;
import touch.baton.domain.tag.query.repository.TagQuerydslRepository;

@Repository
public class TestTagQuerydslRepository extends TagQuerydslRepository {

public TestTagQuerydslRepository(final JPAQueryFactory queryFactory) {
super(queryFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,56 @@

import org.junit.jupiter.api.Test;
import touch.baton.assure.runnerpost.support.command.RunnerPostCreateSupport;
import touch.baton.assure.tag.support.query.TagAssuredSupport;
import touch.baton.assure.tag.support.query.TagQuerySupport;
import touch.baton.config.AssuredTestConfig;
import touch.baton.config.infra.auth.oauth.authcode.FakeAuthCodes;
import touch.baton.domain.tag.command.Tag;
import touch.baton.domain.tag.command.vo.TagReducedName;
import touch.baton.domain.tag.query.controller.response.TagSearchResponses;

import java.time.LocalDateTime;
import java.util.List;

import static touch.baton.assure.runnerpost.support.command.RunnerPostCreateSupport.러너_게시글_생성_요청;
import static touch.baton.assure.tag.support.query.TagAssuredSupport.태그_검색_Detail_응답;


@SuppressWarnings("NonAsciiCharacters")
class TagReadAssuredTest extends AssuredTestConfig {

@Test
void 태그_검색에_성공한다() {
void 입력된_문자열로_태그_목록_검색에_성공한다() {
// given
final String 헤나_액세스_토큰 = oauthLoginTestManager.소셜_회원입을_진행한__액세스_토큰을_반환한다(FakeAuthCodes.hyenaAuthCode());
러너_게시글_생성을_성공하고_러너_게시글_식별자값을_반환한다(헤나_액세스_토큰, List.of("java", "javascript", "script"));
final TagReducedName reducedName = TagReducedName.from("ja");
final List<Tag> 검색된_태그_목록 = tagRepository.readTagsByReducedName(reducedName);
러너_게시글과_태그를_생성한다(헤나_액세스_토큰, List.of("java", "javascript", "script"));

final TagReducedName 요청할_태그_이름 = TagReducedName.nullableInstance("ja");

// when, then
TagAssuredSupport
final List<Tag> 검색된_태그_목록 = tagQueryRepository.findByTagReducedName(요청할_태그_이름, 10);

TagQuerySupport
.클라이언트_요청()
.액세스_토큰으로_로그인한다(헤나_액세스_토큰)
.태그_이름을_오름차순으로_10_검색한다("ja")
.입력된_문자열로_태그_목록을_검색한다(요청할_태그_이름)

.서버_응답()
.태그_검색_성공을_검증한다(
태그_검색_Detail_응답(검색된_태그_목록)
.입력된_문자열로_태그_목록_검색_성공을_검증한다(
TagSearchResponses.Detail.from(검색된_태그_목록)
);
}

private void 러너_게시글_생성을_성공하고_러너_게시글_식별자값을_반환한다(final String 헤나_액세스_토큰, final List<String> 태그_목록) {
private void 러너_게시글과_태그를_생성한다(final String 액세스_토큰, final List<String> 태그_목록) {
RunnerPostCreateSupport
.클라이언트_요청()
.액세스_토큰으로_로그인한다(헤나_액세스_토큰)
.러너_게시글_등록_요청한다(
러너_게시글_생성_요청(
"테스트용_러너_게시글_제목",
태그_목록,
"https://test-pull-request.com",
LocalDateTime.now().plusHours(100),
"테스트용_러너_게시글_구현_내용",
"테스트용_러너_게시글_궁금한_내용",
"테스트용_러너_게시글_참고_사항"
)
)
.액세스_토큰으로_로그인한다(액세스_토큰)
.러너_게시글_등록_요청한다(러너_게시글_생성_요청(
"테스트용_러너_게시글_제목",
태그_목록,
"https://test-pull-request.com",
LocalDateTime.now().plusHours(100),
"테스트용_러너_게시글_구현_내용",
"테스트용_러너_게시글_궁금한_내용",
"테스트용_러너_게시글_참고_사항"
))

.서버_응답()
.러너_게시글_생성_성공을_검증한다();
Expand Down

This file was deleted.

Loading

0 comments on commit 5bcaebd

Please sign in to comment.