From 39ba09ccecd7d8fe7997158dd17ccb7b3d80fc94 Mon Sep 17 00:00:00 2001 From: dragontaek-lee Date: Mon, 24 Jun 2024 00:47:24 +0900 Subject: [PATCH 1/6] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/gam/api/ApiApplication.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/gam/api/ApiApplication.java b/src/main/java/com/gam/api/ApiApplication.java index 1394475d..6a03f8e6 100644 --- a/src/main/java/com/gam/api/ApiApplication.java +++ b/src/main/java/com/gam/api/ApiApplication.java @@ -2,7 +2,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication public class ApiApplication { From f79a94039eca6388756173fb8feeb6af6b452580 Mon Sep 17 00:00:00 2001 From: dragontaek-lee Date: Mon, 24 Jun 2024 00:47:40 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20work=20fetchJoin=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gam/api/domain/user/repository/UserRepository.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/gam/api/domain/user/repository/UserRepository.java b/src/main/java/com/gam/api/domain/user/repository/UserRepository.java index 7032368b..eaa362ed 100644 --- a/src/main/java/com/gam/api/domain/user/repository/UserRepository.java +++ b/src/main/java/com/gam/api/domain/user/repository/UserRepository.java @@ -15,6 +15,9 @@ public interface UserRepository extends JpaRepository { Optional getUserById(Long userId); boolean existsByUserName(String userName); + @Query("SELECT u FROM User u JOIN FETCH u.works WHERE u.id = :userId") + Optional getUserByIdWithWorks(@Param("userId") Long userId); + List findByUserStatusAndFirstWorkIdIsNotNullOrderByScrapCountDesc(UserStatus userStatus); @Query(value = "SELECT u FROM User u WHERE LOWER(u.userName) LIKE %:keyword% ORDER BY u.createdAt DESC") From a1a4307b1e4a7548fcd118a60d1fd769a2e9e20f Mon Sep 17 00:00:00 2001 From: dragontaek-lee Date: Mon, 24 Jun 2024 00:48:08 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20work=20viewCount=20updateMany=20?= =?UTF-8?q?=EC=BF=BC=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gam/api/domain/work/repository/WorkRepository.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/gam/api/domain/work/repository/WorkRepository.java b/src/main/java/com/gam/api/domain/work/repository/WorkRepository.java index df74679e..c0ad41fe 100644 --- a/src/main/java/com/gam/api/domain/work/repository/WorkRepository.java +++ b/src/main/java/com/gam/api/domain/work/repository/WorkRepository.java @@ -1,7 +1,9 @@ package com.gam.api.domain.work.repository; import com.gam.api.domain.work.entity.Work; +import io.lettuce.core.dynamic.annotation.Param; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import java.util.List; @@ -18,4 +20,8 @@ public interface WorkRepository extends JpaRepository { @Query(value = "SELECT w FROM Work w WHERE LOWER(w.title) LIKE LOWER(CONCAT('%', :keyword, '%')) ORDER BY w.createdAt DESC") List findByKeyword(String keyword); Optional findFirstByUserIdAndIsActiveOrderByCreatedAtDesc(Long userId, boolean isActive); + + @Modifying + @Query("UPDATE Work w SET w.viewCount = w.viewCount + 1 WHERE w.id IN :ids") + void updateWorksViewCount(@Param("ids") List ids); } From 84b87d8a6b81829db4f1d1428c996ee68c324ccb Mon Sep 17 00:00:00 2001 From: dragontaek-lee Date: Mon, 24 Jun 2024 00:50:03 +0900 Subject: [PATCH 4/6] =?UTF-8?q?refactor:=20=EC=BF=BC=EB=A6=AC=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20=EC=9E=91=EC=97=85=20user=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EC=8B=9C=20work=20fetchJoin=20=EB=90=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20work=20viewCount=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80=EC=8B=9C=20=ED=95=9C=EB=B2=88?= =?UTF-8?q?=EC=9D=98=20=EC=BF=BC=EB=A6=AC=EB=A1=9C=20=EB=AA=A8=EB=91=90=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=EB=90=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20work=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=EB=AC=BC=20=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B3=A0=20?= =?UTF-8?q?=EB=8C=80=ED=91=9C=20=EC=9E=91=EC=97=85=EB=AC=BC=EC=9D=84=20?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20=EB=91=90=EA=B0=9C?= =?UTF-8?q?=EC=9D=98=20=EC=BF=BC=EB=A6=AC=EA=B0=80=20=EC=95=84=EB=8B=8C=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84=20=EC=9E=90=EC=9B=90=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A0=AC=20=EB=B0=8F=20=EC=A0=95=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=ED=96=89=EB=90=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/service/UserServiceImpl.java | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java b/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java index faf3c806..51f4458f 100644 --- a/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java +++ b/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java @@ -265,12 +265,20 @@ public WorkPortfolioListResponseDTO getMyPortfolio(Long userId) { @Transactional @Override public WorkPortfolioGetResponseDTO getPortfolio(Long requestUserId, Long userId) { + // TODO: spring security에서 주입 val requestUser = findUser(requestUserId); - val user = findUser(userId); + + val user = findUserWithWorks(userId); user.setViewCount(user.getViewCount() + 1); - val works = getUserPortfolios(userId); - works.forEach(w -> w.viewCountUp()); + val works = refineWorkList(user.getWorks()); + val workIds = works.stream() + .map(Work::getId) + .toList(); + + workRepository.updateWorksViewCount(workIds); + + // TODO: spring security에서 주입 val scrapList = requestUser.getUserScraps().stream() .map(UserScrap::getTargetId) .toList(); @@ -365,11 +373,25 @@ private List getUserPortfolios(Long userId) { return works; } + private List refineWorkList(List works) { + return works + .stream() + .filter(Work::isActive) + .sorted(Comparator.comparing(Work::isFirst, Comparator.reverseOrder()) + .thenComparing(Comparator.comparing(Work::getCreatedAt).reversed())) + .collect(Collectors.toList()); + } + private User findUser(Long userId) { return userRepository.findById(userId) .orElseThrow(() -> new EntityNotFoundException(ExceptionMessage.NOT_FOUND_USER.getMessage())); } + private User findUserWithWorks(Long userId) { + return userRepository.getUserByIdWithWorks(userId) + .orElseThrow(() -> new EntityNotFoundException(ExceptionMessage.NOT_FOUND_USER.getMessage())); + } + private void createUserScrap(User user, Long targetId, User targetUser){ userScrapRepository.save(UserScrap.builder() From 8a9fca3685ffb7576492457aad178e68922e4820 Mon Sep 17 00:00:00 2001 From: dragontaek-lee Date: Tue, 25 Jun 2024 01:03:51 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20AuthenticationPrincipal=20GamUserDe?= =?UTF-8?q?tails=20User=20=EA=B0=9D=EC=B2=B4=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gam/api/domain/user/controller/UserController.java | 2 +- .../com/gam/api/domain/user/entity/GamUserDetails.java | 7 +++++++ .../api/domain/user/service/UserDetailsServiceImpl.java | 2 +- .../java/com/gam/api/domain/user/service/UserService.java | 3 ++- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/gam/api/domain/user/controller/UserController.java b/src/main/java/com/gam/api/domain/user/controller/UserController.java index 887f0ce0..e970b96c 100644 --- a/src/main/java/com/gam/api/domain/user/controller/UserController.java +++ b/src/main/java/com/gam/api/domain/user/controller/UserController.java @@ -62,7 +62,7 @@ ResponseEntity getPortfolio( @AuthenticationPrincipal GamUserDetails userDetails, @PathVariable Long userId) { - val response = userService.getPortfolio(userDetails.getId(), userId); + val response = userService.getPortfolio(userDetails.getUser(), userId); return ResponseEntity.ok(ApiResponse.success(ResponseMessage.SUCCESS_GET_PROTFOLIO_LIST.getMessage(), response)); } diff --git a/src/main/java/com/gam/api/domain/user/entity/GamUserDetails.java b/src/main/java/com/gam/api/domain/user/entity/GamUserDetails.java index 28d4f39d..7f4c5a9a 100644 --- a/src/main/java/com/gam/api/domain/user/entity/GamUserDetails.java +++ b/src/main/java/com/gam/api/domain/user/entity/GamUserDetails.java @@ -11,7 +11,9 @@ @Getter public class GamUserDetails implements UserDetails { + // TODO: User 객체 이전 이후 삭제 필요 private final Long id; + private final User user; private final String username; private final String authUserId; private List authorities; @@ -21,6 +23,11 @@ public List getAuthorities() { return authorities; } + public User getUser() { + return user; + } + + // TODO: User 객체 이전 이후 삭제 필요 public Long getId() { return id; } diff --git a/src/main/java/com/gam/api/domain/user/service/UserDetailsServiceImpl.java b/src/main/java/com/gam/api/domain/user/service/UserDetailsServiceImpl.java index 4c993b2c..138ca937 100644 --- a/src/main/java/com/gam/api/domain/user/service/UserDetailsServiceImpl.java +++ b/src/main/java/com/gam/api/domain/user/service/UserDetailsServiceImpl.java @@ -11,7 +11,6 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Service; - import javax.persistence.EntityNotFoundException; import java.util.ArrayList; import java.util.List; @@ -41,6 +40,7 @@ public UserDetails loadUserByUsername(String userId) { return GamUserDetails.builder() .id(user.getId()) + .user(user) .authUserId(authUserId) .username(user.getUserName()) .authorities(authorities) diff --git a/src/main/java/com/gam/api/domain/user/service/UserService.java b/src/main/java/com/gam/api/domain/user/service/UserService.java index 1af98f81..25bf7cc5 100644 --- a/src/main/java/com/gam/api/domain/user/service/UserService.java +++ b/src/main/java/com/gam/api/domain/user/service/UserService.java @@ -4,6 +4,7 @@ import com.gam.api.domain.user.dto.response.UserResponseDTO; import com.gam.api.domain.user.dto.response.UserScrapsResponseDTO; import com.gam.api.domain.user.dto.response.SearchUserWorkDTO; +import com.gam.api.domain.user.entity.User; import com.gam.api.domain.work.dto.response.WorkPortfolioGetResponseDTO; import com.gam.api.domain.work.dto.response.WorkPortfolioListResponseDTO; @@ -32,7 +33,7 @@ public interface UserService { List getUserScraps(Long userId); List getPopularDesigners(Long userId); WorkPortfolioListResponseDTO getMyPortfolio(Long userId); - WorkPortfolioGetResponseDTO getPortfolio(Long requestUserId, Long userId); + WorkPortfolioGetResponseDTO getPortfolio(User requestUser, Long userId); List getDiscoveryUsers(Long userId, int[] tags); void updateInstagramLink(Long userId, UserUpdateLinkRequestDTO request); void updateBehanceLink(Long userId, UserUpdateLinkRequestDTO request); From 4119e57835ed12f34da3c728369b125ef220bf82 Mon Sep 17 00:00:00 2001 From: dragontaek-lee Date: Tue, 25 Jun 2024 01:05:48 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20AuthenticationPrincipal=20GamUserDe?= =?UTF-8?q?tails=20User=20=EA=B0=9D=EC=B2=B4=20=EC=82=AC=EC=9A=A9,=20?= =?UTF-8?q?=EB=8B=A8=EC=9D=BC=20scrap=20=EC=A1=B0=ED=9A=8C=EB=A1=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=9E=A9=20=EC=97=AC=EB=B6=80=20=EA=B2=80?= =?UTF-8?q?=EC=82=AC=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/repository/UserScrapRepository.java | 4 ++++ .../api/domain/user/service/UserServiceImpl.java | 13 +++---------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/gam/api/domain/user/repository/UserScrapRepository.java b/src/main/java/com/gam/api/domain/user/repository/UserScrapRepository.java index 6b8877a0..5331c7cd 100644 --- a/src/main/java/com/gam/api/domain/user/repository/UserScrapRepository.java +++ b/src/main/java/com/gam/api/domain/user/repository/UserScrapRepository.java @@ -1,5 +1,6 @@ package com.gam.api.domain.user.repository; +import com.gam.api.domain.user.entity.User; import com.gam.api.domain.user.entity.UserScrap; import com.gam.api.domain.user.dto.query.UserScrapQueryDto; import org.springframework.data.jpa.repository.JpaRepository; @@ -9,8 +10,11 @@ import org.springframework.data.repository.query.Param; public interface UserScrapRepository extends JpaRepository { + List findUserScrapsByUserId(Long userId); UserScrap findByUser_idAndTargetId(Long userId, Long targetId); + UserScrap findByUserAndTargetId(User user, Long targetId); + @Query("SELECT DISTINCT NEW com.gam.api.domain.user.dto.query.UserScrapQueryDto(us.id, us.modifiedAt, us.targetId) "+ "FROM UserScrap us " + "LEFT JOIN FETCH User tu ON us.targetId = tu.id " + diff --git a/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java b/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java index 51f4458f..833dab39 100644 --- a/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java +++ b/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java @@ -264,10 +264,7 @@ public WorkPortfolioListResponseDTO getMyPortfolio(Long userId) { @Transactional @Override - public WorkPortfolioGetResponseDTO getPortfolio(Long requestUserId, Long userId) { - // TODO: spring security에서 주입 - val requestUser = findUser(requestUserId); - + public WorkPortfolioGetResponseDTO getPortfolio(User requestUser, Long userId) { val user = findUserWithWorks(userId); user.setViewCount(user.getViewCount() + 1); val works = refineWorkList(user.getWorks()); @@ -278,12 +275,8 @@ public WorkPortfolioGetResponseDTO getPortfolio(Long requestUserId, Long userId) workRepository.updateWorksViewCount(workIds); - // TODO: spring security에서 주입 - val scrapList = requestUser.getUserScraps().stream() - .map(UserScrap::getTargetId) - .toList(); - - val isScraped = scrapList.contains(user.getId()); + val userScrap = userScrapRepository.findByUserAndTargetId(requestUser, user.getId()); + val isScraped = Objects.isNull(userScrap); return WorkPortfolioGetResponseDTO.of(isScraped, user, works); }