From 4e3c96c200f0b3ba14b72256cc141f7e35a57a30 Mon Sep 17 00:00:00 2001 From: Parkjyun <98092394+Parkjyun@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:13:58 +0900 Subject: [PATCH] =?UTF-8?q?[feat]=20redis=20=EC=9D=98=EC=A1=B4=EC=84=B1=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=9C=A0=EC=A0=80=EC=9D=98=20?= =?UTF-8?q?=EB=8C=80=ED=95=99=EA=B5=90=20=EC=84=A4=EC=A0=95=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=A0=80=EC=9E=A5=20=EB=B0=8F=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20api=20=EC=83=9D=EC=84=B1=20(#40)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [dependency] add redis dependency * [feat] create redis hash * [feat] create errorcode for user's university update * [feat] create redis repository for UserUniversity * [feat] create helper class for UserUniversity * [feat] create post user's university api * [feat] create get user's university api --- build.gradle | 3 ++ .../api/user/controller/UserController.java | 34 +++++++++++++++++++ .../request/UserUniversityPostRequest.java | 7 ++++ .../api/user/service/UserCommandService.java | 22 ++++++++++++ .../api/user/service/UserQueryService.java | 21 ++++++++++++ .../user/service/UserUniversityDeleter.java | 20 +++++++++++ .../user/service/UserUniversityFinder.java | 19 +++++++++++ .../user/service/UserUniversityUpdater.java | 17 ++++++++++ .../command/UserUniversityPostCommand.java | 22 ++++++++++++ .../response/UserUniversityFindResponse.java | 13 +++++++ .../common/code/UserUniversityErrorCode.java | 14 ++++++++ .../domain/user/model/UserUniversity.java | 30 ++++++++++++++++ .../repository/UserUniversityRepository.java | 12 +++++++ 13 files changed, 234 insertions(+) create mode 100644 src/main/java/org/hankki/hankkiserver/api/user/controller/UserController.java create mode 100644 src/main/java/org/hankki/hankkiserver/api/user/controller/request/UserUniversityPostRequest.java create mode 100644 src/main/java/org/hankki/hankkiserver/api/user/service/UserCommandService.java create mode 100644 src/main/java/org/hankki/hankkiserver/api/user/service/UserQueryService.java create mode 100644 src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityDeleter.java create mode 100644 src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityFinder.java create mode 100644 src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityUpdater.java create mode 100644 src/main/java/org/hankki/hankkiserver/api/user/service/command/UserUniversityPostCommand.java create mode 100644 src/main/java/org/hankki/hankkiserver/api/user/service/response/UserUniversityFindResponse.java create mode 100644 src/main/java/org/hankki/hankkiserver/common/code/UserUniversityErrorCode.java create mode 100644 src/main/java/org/hankki/hankkiserver/domain/user/model/UserUniversity.java create mode 100644 src/main/java/org/hankki/hankkiserver/domain/user/repository/UserUniversityRepository.java diff --git a/build.gradle b/build.gradle index 7dd46b61..d92528d1 100644 --- a/build.gradle +++ b/build.gradle @@ -55,6 +55,9 @@ dependencies { // Feign implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.2' + + // Redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' } tasks.named('test') { diff --git a/src/main/java/org/hankki/hankkiserver/api/user/controller/UserController.java b/src/main/java/org/hankki/hankkiserver/api/user/controller/UserController.java new file mode 100644 index 00000000..b41cc82e --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/api/user/controller/UserController.java @@ -0,0 +1,34 @@ +package org.hankki.hankkiserver.api.user.controller; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.hankki.hankkiserver.api.dto.HankkiResponse; +import org.hankki.hankkiserver.api.user.controller.request.UserUniversityPostRequest; +import org.hankki.hankkiserver.api.user.service.UserCommandService; +import org.hankki.hankkiserver.api.user.service.UserQueryService; +import org.hankki.hankkiserver.api.user.service.command.UserUniversityPostCommand; +import org.hankki.hankkiserver.api.user.service.response.UserUniversityFindResponse; +import org.hankki.hankkiserver.auth.UserId; +import org.hankki.hankkiserver.common.code.CommonSuccessCode; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/v1") +@RequiredArgsConstructor +public class UserController { + + private final UserCommandService userCommandService; + private final UserQueryService userQueryService; + + @PostMapping("/users/me/university") + public HankkiResponse postUserUniversity(@UserId final Long userId, + @Valid @RequestBody final UserUniversityPostRequest request) { + userCommandService.saveUserUniversity(new UserUniversityPostCommand(userId, request)); + return HankkiResponse.success(CommonSuccessCode.CREATED); + } + + @GetMapping("/users/me/university") + public HankkiResponse findUserUniversity(@UserId final Long userId) { + return HankkiResponse.success(CommonSuccessCode.OK, userQueryService.findUserUniversity(userId)); + } +} diff --git a/src/main/java/org/hankki/hankkiserver/api/user/controller/request/UserUniversityPostRequest.java b/src/main/java/org/hankki/hankkiserver/api/user/controller/request/UserUniversityPostRequest.java new file mode 100644 index 00000000..1de3d460 --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/api/user/controller/request/UserUniversityPostRequest.java @@ -0,0 +1,7 @@ +package org.hankki.hankkiserver.api.user.controller.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public record UserUniversityPostRequest(long universityId, @NotBlank @Size(max = 5) String name, double longitude, double latitude) { +} diff --git a/src/main/java/org/hankki/hankkiserver/api/user/service/UserCommandService.java b/src/main/java/org/hankki/hankkiserver/api/user/service/UserCommandService.java new file mode 100644 index 00000000..b62e30c4 --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/api/user/service/UserCommandService.java @@ -0,0 +1,22 @@ +package org.hankki.hankkiserver.api.user.service; + +import lombok.RequiredArgsConstructor; +import org.hankki.hankkiserver.api.user.service.command.UserUniversityPostCommand; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class UserCommandService { + + private final UserUniversityUpdater userUniversityUpdater; + private final UserUniversityDeleter userUniversityDeleter; + private final UserUniversityFinder userUniversityFinder; + + @Transactional + public void saveUserUniversity(UserUniversityPostCommand userUniversityPostCommand) { + userUniversityFinder.findByUserId(userUniversityPostCommand.userId()) + .ifPresent(userUniversity -> userUniversityDeleter.deleteById(userUniversity.getId())); + userUniversityUpdater.save(userUniversityPostCommand.toEntity()); + } +} diff --git a/src/main/java/org/hankki/hankkiserver/api/user/service/UserQueryService.java b/src/main/java/org/hankki/hankkiserver/api/user/service/UserQueryService.java new file mode 100644 index 00000000..0edbf3cf --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/api/user/service/UserQueryService.java @@ -0,0 +1,21 @@ +package org.hankki.hankkiserver.api.user.service; + +import lombok.RequiredArgsConstructor; +import org.hankki.hankkiserver.api.user.service.response.UserUniversityFindResponse; +import org.hankki.hankkiserver.common.code.UserUniversityErrorCode; +import org.hankki.hankkiserver.common.exception.NotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class UserQueryService { + + private final UserUniversityFinder userUniversityFinder; + + @Transactional(readOnly = true) + public UserUniversityFindResponse findUserUniversity(Long userId) { + return UserUniversityFindResponse.of(userUniversityFinder.findByUserId(userId) + .orElseThrow(() -> new NotFoundException(UserUniversityErrorCode.USER_UNIVERSITY_NOT_FOUND))); + } +} diff --git a/src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityDeleter.java b/src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityDeleter.java new file mode 100644 index 00000000..747438dc --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityDeleter.java @@ -0,0 +1,20 @@ +package org.hankki.hankkiserver.api.user.service; + +import lombok.RequiredArgsConstructor; +import org.hankki.hankkiserver.domain.user.repository.UserUniversityRepository; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class UserUniversityDeleter { + + private final UserUniversityRepository userUniversityRepository; + + protected void deleteById(Long id) { + userUniversityRepository.deleteById(id); + } + + protected void deleteByUserId(Long userId) { + userUniversityRepository.deleteByUserId(userId); + } +} diff --git a/src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityFinder.java b/src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityFinder.java new file mode 100644 index 00000000..56f920b8 --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityFinder.java @@ -0,0 +1,19 @@ +package org.hankki.hankkiserver.api.user.service; + +import lombok.RequiredArgsConstructor; +import org.hankki.hankkiserver.domain.user.model.UserUniversity; +import org.hankki.hankkiserver.domain.user.repository.UserUniversityRepository; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component +@RequiredArgsConstructor +public class UserUniversityFinder { + + private final UserUniversityRepository userUniversityRepository; + + public Optional findByUserId(Long userId) { + return userUniversityRepository.findByUserId(userId); + } +} diff --git a/src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityUpdater.java b/src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityUpdater.java new file mode 100644 index 00000000..dd15d8db --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/api/user/service/UserUniversityUpdater.java @@ -0,0 +1,17 @@ +package org.hankki.hankkiserver.api.user.service; + +import lombok.RequiredArgsConstructor; +import org.hankki.hankkiserver.domain.user.model.UserUniversity; +import org.hankki.hankkiserver.domain.user.repository.UserUniversityRepository; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class UserUniversityUpdater { + + private final UserUniversityRepository userUniversityRepository; + + protected void save(UserUniversity userUniversity) { + userUniversityRepository.save(userUniversity).getUserId(); + } +} diff --git a/src/main/java/org/hankki/hankkiserver/api/user/service/command/UserUniversityPostCommand.java b/src/main/java/org/hankki/hankkiserver/api/user/service/command/UserUniversityPostCommand.java new file mode 100644 index 00000000..84636716 --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/api/user/service/command/UserUniversityPostCommand.java @@ -0,0 +1,22 @@ +package org.hankki.hankkiserver.api.user.service.command; + +import org.hankki.hankkiserver.api.user.controller.request.UserUniversityPostRequest; +import org.hankki.hankkiserver.domain.user.model.UserUniversity; + +public record UserUniversityPostCommand(Long userId, Long universityId, String universityName, + double longitude, double latitude) { + public UserUniversityPostCommand(Long userId, UserUniversityPostRequest request) { + this(userId, request.universityId(), request.name(), request.longitude(), request.latitude()); + } + + public UserUniversity toEntity() { + return UserUniversity.builder() + .userId(userId) + .universityId(universityId) + .universityName(universityName) + .longitude(longitude) + .latitude(latitude) + .build(); + } +} + diff --git a/src/main/java/org/hankki/hankkiserver/api/user/service/response/UserUniversityFindResponse.java b/src/main/java/org/hankki/hankkiserver/api/user/service/response/UserUniversityFindResponse.java new file mode 100644 index 00000000..ef947a13 --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/api/user/service/response/UserUniversityFindResponse.java @@ -0,0 +1,13 @@ +package org.hankki.hankkiserver.api.user.service.response; + +import org.hankki.hankkiserver.domain.user.model.UserUniversity; + +public record UserUniversityFindResponse(long id, + String name, + double longitude, + double latitude) { + public static UserUniversityFindResponse of (UserUniversity userUniversity) { + return new UserUniversityFindResponse(userUniversity.getUniversityId(), userUniversity.getUniversityName(), + userUniversity.getLongitude(), userUniversity.getLatitude()); + } +} diff --git a/src/main/java/org/hankki/hankkiserver/common/code/UserUniversityErrorCode.java b/src/main/java/org/hankki/hankkiserver/common/code/UserUniversityErrorCode.java new file mode 100644 index 00000000..70f0189d --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/common/code/UserUniversityErrorCode.java @@ -0,0 +1,14 @@ +package org.hankki.hankkiserver.common.code; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum UserUniversityErrorCode implements ErrorCode { + USER_UNIVERSITY_NOT_FOUND(HttpStatus.NOT_FOUND, "대학 정보를 찾을 수 없습니다."); + + private final HttpStatus httpStatus; + private final String message; +} diff --git a/src/main/java/org/hankki/hankkiserver/domain/user/model/UserUniversity.java b/src/main/java/org/hankki/hankkiserver/domain/user/model/UserUniversity.java new file mode 100644 index 00000000..5bf33e52 --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/domain/user/model/UserUniversity.java @@ -0,0 +1,30 @@ +package org.hankki.hankkiserver.domain.user.model; + +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import org.springframework.data.redis.core.RedisHash; +import org.springframework.data.redis.core.index.Indexed; + +@RedisHash(value = "UserUniversity", timeToLive = 60 * 60 * 24 * 1000L * 30) +@Builder +@AllArgsConstructor +@Getter +public class UserUniversity { + + @Id + private Long id; + + @Indexed + private Long userId; + + private Long universityId; + + private String universityName; + + private Double longitude; + + private Double latitude; + +} \ No newline at end of file diff --git a/src/main/java/org/hankki/hankkiserver/domain/user/repository/UserUniversityRepository.java b/src/main/java/org/hankki/hankkiserver/domain/user/repository/UserUniversityRepository.java new file mode 100644 index 00000000..cc60ccc1 --- /dev/null +++ b/src/main/java/org/hankki/hankkiserver/domain/user/repository/UserUniversityRepository.java @@ -0,0 +1,12 @@ +package org.hankki.hankkiserver.domain.user.repository; + +import org.hankki.hankkiserver.domain.user.model.UserUniversity; +import org.springframework.data.repository.CrudRepository; + +import java.util.Optional; + +public interface UserUniversityRepository extends CrudRepository { + Optional findByUserId(Long userId); + void deleteById(Long id); + void deleteByUserId(Long userId); +}