Skip to content

Commit

Permalink
️refactor: 조회 서비스 분리 (#371)
Browse files Browse the repository at this point in the history
* refactor: 검색 api 북마크 여부 response 추가

* refactor: querydsl 검색 쿼리 수정

* refactor: hibernate batchSize 옵션 추가

* refactor: ddl-auto 옵션 변경

* refactor: OrganizationQueryService 분리

* refactor: PortfolioQueryService 분리
  • Loading branch information
seheonnn authored Aug 2, 2024
1 parent b7e3bdb commit 2c0e249
Show file tree
Hide file tree
Showing 17 changed files with 271 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@
import com.sponus.coredomain.domain.organization.enums.OrganizationType;
import com.sponus.coreinfrasecurity.annotation.AuthOrganization;
import com.sponus.sponusbe.domain.organization.club.service.ClubService;
import com.sponus.sponusbe.domain.organization.company.dto.OrganizationGetResponse;
import com.sponus.sponusbe.domain.organization.company.service.CompanyService;
import com.sponus.sponusbe.domain.organization.dto.request.OrganizationCreateRequest;
import com.sponus.sponusbe.domain.organization.dto.request.OrganizationSearchRequest;
import com.sponus.sponusbe.domain.organization.dto.request.PageCondition;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationGetResponse;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationImageUploadResponse;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationSearchResponse;
import com.sponus.sponusbe.domain.organization.dto.response.PageResponse;
import com.sponus.sponusbe.domain.organization.service.OrganizationQueryService;
import com.sponus.sponusbe.domain.organization.service.OrganizationService;

import jakarta.validation.Valid;
Expand All @@ -39,6 +40,7 @@
@RequiredArgsConstructor
public class OrganizationController {
private final OrganizationService organizationService;
private final OrganizationQueryService organizationQueryService;
private final ClubService clubService;
private final CompanyService companyService;

Expand All @@ -53,7 +55,7 @@ public ApiResponse<PageResponse<OrganizationGetResponse>> getOrganizations(
@ModelAttribute @Valid PageCondition pageCondition,
@ModelAttribute @Valid OrganizationType organizationType) {
return ApiResponse.onSuccess(
organizationService.getOrganizations(authOrganization, pageCondition, organizationType));
organizationQueryService.getOrganizations(authOrganization, pageCondition, organizationType));
}

@GetMapping("/me")
Expand All @@ -75,7 +77,7 @@ public ApiResponse<OrganizationImageUploadResponse> uploadProfileImage(

@GetMapping("/exists")
public ApiResponse<Boolean> verifyName(@RequestParam String name) {
return ApiResponse.onSuccess(organizationService.verifyName(name));
return ApiResponse.onSuccess(organizationQueryService.verifyName(name));
}

@DeleteMapping("/{organizationId}")
Expand All @@ -91,7 +93,7 @@ public ApiResponse<PageResponse<OrganizationSearchResponse>> searchOrganization(
@AuthOrganization Organization organization
) {
return ApiResponse.onSuccess(
organizationService.searchOrganizations(pageCondition, keyword, organization.getId()));
organizationQueryService.searchOrganizations(pageCondition, keyword, organization));
}

@DeleteMapping("/search")
Expand All @@ -109,7 +111,7 @@ public ApiResponse<Void> createSearchHistory(@AuthOrganization Organization orga

@GetMapping("/search/keywords")
public ApiResponse<List<String>> getSearchHistory(@AuthOrganization Organization organization) {
return ApiResponse.onSuccess(organizationService.getSearchHistory(organization.getId()));
return ApiResponse.onSuccess(organizationQueryService.getSearchHistory(organization.getId()));
}

@DeleteMapping("/search/keywords")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.sponus.sponusbe.domain.organization.company.dto;
package com.sponus.sponusbe.domain.organization.dto.response;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ public record OrganizationSearchResponse(
Long id,
String name,
String imageUrl,
OrganizationType organizationType
OrganizationType organizationType,
boolean isBookmarked
) {
public static OrganizationSearchResponse of(Organization organization) {
public static OrganizationSearchResponse of(Organization organization, boolean isBookmarked) {
return OrganizationSearchResponse.builder()
.id(organization.getId())
.name(organization.getName())
.imageUrl(organization.getImageUrl())
.organizationType(organization.getOrganizationType())
.isBookmarked(isBookmarked)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package com.sponus.sponusbe.domain.organization.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coredomain.domain.organization.enums.OrganizationType;
import com.sponus.coredomain.domain.organization.enums.ProfileStatus;
import com.sponus.coredomain.domain.organization.repository.OrganizationRepository;
import com.sponus.coredomain.domain.organization.repository.querydsl.conditions.OrganizationSearchCondition;
import com.sponus.coreinfraredis.entity.SearchHistory;
import com.sponus.coreinfraredis.repository.SearchHistoryRepository;
import com.sponus.sponusbe.domain.organization.dto.request.PageCondition;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationGetResponse;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationSearchResponse;
import com.sponus.sponusbe.domain.organization.dto.response.PageResponse;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

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

private final OrganizationRepository organizationRepository;
private final SearchHistoryRepository searchHistoryRepository;

public Boolean verifyName(String name) {
return organizationRepository.existsByName(name);
}

public PageResponse<OrganizationGetResponse> getOrganizations(
Organization authOrganization,
PageCondition pageCondition,
OrganizationType organizationType) {
// TODO: FETCH JOIN으로 변경
Set<Long> bookmarkedOrganizationIds = authOrganization.getBookmarks()
.stream()
.map(bookmark -> bookmark.getTarget().getId())
.collect(Collectors.toSet());
Pageable pageable = PageRequest.of(pageCondition.getPage() - 1, pageCondition.getSize());
List<OrganizationGetResponse> organizations = organizationRepository.findOrganizations(
organizationType, pageable, authOrganization.getId())
.stream()
.map(organization ->
OrganizationGetResponse.of(organization, bookmarkedOrganizationIds.contains(organization.getId())))
.toList();

return PageResponse.of(
PageableExecutionUtils.getPage(organizations, pageable,
() -> organizationRepository.countByOrganizationType(organizationType)));
}

public PageResponse<OrganizationSearchResponse> searchOrganizations(PageCondition pageCondition, String keyword,
Organization authOrganization) {

Set<Long> bookmarkedOrganizationIds = authOrganization.getBookmarks()
.stream()
.map(bookmark -> bookmark.getTarget().getId())
.collect(Collectors.toSet());
Pageable pageable = PageRequest.of(pageCondition.getPage() - 1, pageCondition.getSize());

List<OrganizationSearchResponse> organizations = organizationRepository.findByNameContains(
keyword, pageable)
.stream()
.filter(organization -> organization.getProfileStatus().equals(ProfileStatus.ACTIVE))
.filter(organization -> !organization.getId().equals(authOrganization.getId()))
.map(organization ->
OrganizationSearchResponse.of(organization, bookmarkedOrganizationIds.contains(organization.getId())))
.toList();

return PageResponse.of(
PageableExecutionUtils.getPage(organizations, pageable,
() -> organizationRepository.countByNameContains(keyword)));
}

public PageResponse<OrganizationSearchResponse> searchOrganizationsV2(
PageCondition pageCondition, String keyword,
Organization authOrganization) {

OrganizationSearchCondition condition = OrganizationSearchCondition.of(keyword, authOrganization.getId());
Pageable pageable = PageRequest.of(pageCondition.getPage() - 1, pageCondition.getSize());

Page<Organization> organizations = organizationRepository.searchOrganizationV2(condition, pageable);

Set<Long> bookmarkedOrganizationIds = authOrganization.getBookmarks()
.stream()
.map(bookmark -> bookmark.getTarget().getId())
.collect(Collectors.toSet());

return PageResponse.of(organizations.map(organization ->
OrganizationSearchResponse.of(organization, bookmarkedOrganizationIds.contains(organization.getId()))));
}

public List<String> getSearchHistory(Long organizationId) {
Set<String> searchHistory = findSearchHistory(organizationId).getKeywords();

List<String> searchHistoryList = new ArrayList<>(searchHistory);
searchHistoryList.removeIf(String::isEmpty);

if (!searchHistoryList.isEmpty()) {
Collections.reverse(searchHistoryList);
}

return searchHistoryList;
}

private SearchHistory findSearchHistory(Long organizationId) {
return searchHistoryRepository.findById(organizationId).orElseGet(() -> {
SearchHistory newSearchHistory = SearchHistory.builder()
.organizationId(organizationId)
.build();
return searchHistoryRepository.save(newSearchHistory);
});
}

}
Original file line number Diff line number Diff line change
@@ -1,36 +1,20 @@
package com.sponus.sponusbe.domain.organization.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.sponus.coredomain.domain.bookmark.repository.BookmarkRepository;
import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coredomain.domain.organization.club.Club;
import com.sponus.coredomain.domain.organization.company.Company;
import com.sponus.coredomain.domain.organization.enums.OrganizationType;
import com.sponus.coredomain.domain.organization.enums.ProfileStatus;
import com.sponus.coredomain.domain.organization.repository.OrganizationRepository;
import com.sponus.coredomain.domain.organization.repository.conditions.OrganizationSearchCondition;
import com.sponus.coreinfraredis.entity.SearchHistory;
import com.sponus.coreinfraredis.repository.SearchHistoryRepository;
import com.sponus.coreinfras3.S3Service;
import com.sponus.sponusbe.domain.organization.company.dto.OrganizationGetResponse;
import com.sponus.sponusbe.domain.organization.dto.request.OrganizationCreateRequest;
import com.sponus.sponusbe.domain.organization.dto.request.PageCondition;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationImageUploadResponse;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationSearchResponse;
import com.sponus.sponusbe.domain.organization.dto.response.PageResponse;
import com.sponus.sponusbe.domain.organization.exception.OrganizationErrorCode;
import com.sponus.sponusbe.domain.organization.exception.OrganizationException;

Expand All @@ -42,8 +26,8 @@
@Transactional
@RequiredArgsConstructor
public class OrganizationService {

private final OrganizationRepository organizationRepository;
private final BookmarkRepository bookmarkRepository;
private final S3Service s3Service;
private final PasswordEncoder passwordEncoder;
private final SearchHistoryRepository searchHistoryRepository;
Expand All @@ -64,63 +48,11 @@ public OrganizationImageUploadResponse uploadProfileImage(Long organizationId, M
return new OrganizationImageUploadResponse(imageUrl);
}

public Boolean verifyName(String name) {
return organizationRepository.existsByName(name);
}

public void deleteOrganization(Long organizationId) {
Organization organization = findOrganizationById(organizationId);
organization.delete();
}

public PageResponse<OrganizationGetResponse> getOrganizations(
Organization authOrganization,
PageCondition pageCondition,
OrganizationType organizationType) {
// TODO: FETCH JOIN으로 변경
Set<Long> bookmarkedOrganizationIds = bookmarkRepository.findByOrganization(authOrganization).stream()
.map((bookmark) -> bookmark.getTarget().getId())
.collect(Collectors.toSet());
Pageable pageable = PageRequest.of(pageCondition.getPage() - 1, pageCondition.getSize());
List<OrganizationGetResponse> organizations = organizationRepository.findOrganizations(
organizationType, pageable, authOrganization.getId())
.stream()
.map(organization ->
OrganizationGetResponse.of(organization, bookmarkedOrganizationIds.contains(organization.getId())))
.toList();

return PageResponse.of(
PageableExecutionUtils.getPage(organizations, pageable,
() -> organizationRepository.countByOrganizationType(organizationType)));
}

public PageResponse<OrganizationSearchResponse> searchOrganizations(PageCondition pageCondition, String keyword,
Long organizationId) {

Pageable pageable = PageRequest.of(pageCondition.getPage() - 1, pageCondition.getSize());
List<OrganizationSearchResponse> organizations = organizationRepository.findByNameContains(
keyword, pageable)
.stream()
.filter(organization -> organization.getProfileStatus().equals(ProfileStatus.ACTIVE))
.filter(organization -> !organization.getId().equals(organizationId))
.map(OrganizationSearchResponse::of)
.toList();

return PageResponse.of(
PageableExecutionUtils.getPage(organizations, pageable,
() -> organizationRepository.countByNameContains(keyword)));
}

public PageResponse<OrganizationSearchResponse> searchOrganizationsV2(PageCondition pageCondition, String keyword,
Long organizationId) {

OrganizationSearchCondition condition = OrganizationSearchCondition.of(keyword, organizationId);
Pageable pageable = PageRequest.of(pageCondition.getPage() - 1, pageCondition.getSize());

return PageResponse.of(organizationRepository.searchOrganizationV2(condition, pageable)
.map(OrganizationSearchResponse::of));
}

public void createSearchHistory(Long organizationId, String keyword) {
SearchHistory searchHistory = findSearchHistory(organizationId);

Expand All @@ -133,30 +65,7 @@ public void createSearchHistory(Long organizationId, String keyword) {
searchHistoryRepository.save(searchHistory);
}

public List<String> getSearchHistory(Long organizationId) {
Set<String> searchHistory = findSearchHistory(organizationId).getKeywords();

List<String> searchHistoryList = new ArrayList<>(searchHistory);
searchHistoryList.removeIf(String::isEmpty);

if (!searchHistoryList.isEmpty()) {
Collections.reverse(searchHistoryList);
}

return searchHistoryList;
}

public SearchHistory findSearchHistory(Long organizationId) {
return searchHistoryRepository.findById(organizationId).orElseGet(() -> {
SearchHistory newSearchHistory = SearchHistory.builder()
.organizationId(organizationId)
.build();
return searchHistoryRepository.save(newSearchHistory);
});
}

public void deleteSearchKeyword(Long organizationId, String keyword) {
// TODO 검색어 에러 처리
SearchHistory searchHistory = searchHistoryRepository.findById(organizationId)
.orElseThrow(() -> new OrganizationException(OrganizationErrorCode.ORGANIZATION_ERROR));
searchHistory.getKeywords().remove(keyword);
Expand All @@ -174,4 +83,13 @@ private Organization findOrganizationById(Long organizationId) {
return organizationRepository.findById(organizationId)
.orElseThrow(() -> new OrganizationException(OrganizationErrorCode.ORGANIZATION_NOT_FOUND));
}

private SearchHistory findSearchHistory(Long organizationId) {
return searchHistoryRepository.findById(organizationId).orElseGet(() -> {
SearchHistory newSearchHistory = SearchHistory.builder()
.organizationId(organizationId)
.build();
return searchHistoryRepository.save(newSearchHistory);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.sponus.sponusbe.domain.portfolio.dto.PortfolioGetResponse;
import com.sponus.sponusbe.domain.portfolio.dto.PortfolioImageCreateResponse;
import com.sponus.sponusbe.domain.portfolio.dto.PortfolioUpdateRequest;
import com.sponus.sponusbe.domain.portfolio.service.PortfolioQueryService;
import com.sponus.sponusbe.domain.portfolio.service.PortfolioService;

import jakarta.validation.Valid;
Expand All @@ -42,7 +43,9 @@
@RequestMapping(PORTFOLIO_URI)
@RestController
public class PortfolioController {

private final PortfolioService portfolioService;
private final PortfolioQueryService portfolioQueryService;

@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ApiResponse<PortfolioCreateResponse> createPortfolio(
Expand All @@ -57,7 +60,7 @@ public ApiResponse<PortfolioCreateResponse> createPortfolio(
@GetMapping
public ApiResponse<Page<PortfolioGetResponse>> getPortfolios(@PageableDefault() Pageable pageable, @ModelAttribute
PortfolioSearchParam portfolioSearchParam) {
Page<PortfolioGetResponse> response = portfolioService.getPortfolios(portfolioSearchParam, pageable);
Page<PortfolioGetResponse> response = portfolioQueryService.getPortfolios(portfolioSearchParam, pageable);
return ApiResponse.onSuccess(response);
}

Expand Down
Loading

0 comments on commit 2c0e249

Please sign in to comment.