diff --git a/src/main/java/org/websoso/WSSServer/application/LibraryInterestApplication.java b/src/main/java/org/websoso/WSSServer/application/LibraryInterestApplication.java index d2e14d3c..decacb81 100644 --- a/src/main/java/org/websoso/WSSServer/application/LibraryInterestApplication.java +++ b/src/main/java/org/websoso/WSSServer/application/LibraryInterestApplication.java @@ -1,11 +1,8 @@ package org.websoso.WSSServer.application; -import static org.websoso.WSSServer.exception.error.CustomUserNovelError.ALREADY_INTERESTED; import static org.websoso.WSSServer.exception.error.CustomUserNovelError.NOT_INTERESTED; -import static org.websoso.WSSServer.exception.error.CustomUserNovelError.USER_NOVEL_ALREADY_EXISTS; import lombok.RequiredArgsConstructor; -import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.websoso.WSSServer.user.domain.User; @@ -32,21 +29,7 @@ public class LibraryInterestApplication { public void registerAsInterest(User user, Long novelId) { Novel novel = novelService.getNovelOrException(novelId); - UserNovel userNovel = user == null ? null : libraryService.getLibraryOrNull(user, novel); - - if (userNovel != null && userNovel.getIsInterest()) { - throw new CustomUserNovelException(ALREADY_INTERESTED, "already registered as interested"); - } - - if (userNovel == null) { - try { - userNovel = createUserNovelByInterest(user, novel); - } catch (DataIntegrityViolationException e) { - userNovel = libraryService.getLibraryOrException(user, novelId); - } - } - - userNovel.setIsInterest(true); + libraryService.registerInterest(user, novel); } /** @@ -57,25 +40,13 @@ public void registerAsInterest(User user, Long novelId) { */ @Transactional public void unregisterAsInterest(User user, Long novelId) { - UserNovel userNovel = libraryService.getLibraryOrException(user, novelId); + UserNovel library = libraryService.getLibraryOrNull(user, novelId); - if (!userNovel.getIsInterest()) { - throw new CustomUserNovelException(NOT_INTERESTED, "not registered as interest"); - } - - userNovel.setIsInterest(false); - - if (userNovel.getStatus() == null) { - libraryService.delete(userNovel); + if (library == null) { + return; } + libraryService.unregisterInterest(library); } - private UserNovel createUserNovelByInterest(User user, Novel novel) { - if (libraryService.getLibraryOrNull(user, novel) != null) { - throw new CustomUserNovelException(USER_NOVEL_ALREADY_EXISTS, "this novel is already registered"); - } - - return libraryService.createLibrary(null, 0.0f, null, null, user, novel); - } } diff --git a/src/main/java/org/websoso/WSSServer/library/domain/UserNovel.java b/src/main/java/org/websoso/WSSServer/library/domain/UserNovel.java index fca72eb2..66f340d4 100644 --- a/src/main/java/org/websoso/WSSServer/library/domain/UserNovel.java +++ b/src/main/java/org/websoso/WSSServer/library/domain/UserNovel.java @@ -36,6 +36,9 @@ }) public class UserNovel extends BaseEntity { + public static final Float DEFAULT_RATING = 0.0f; + public static final ReadStatus DEFAULT_STATUS = null; + @Id @GeneratedValue(strategy = IDENTITY) @Column(nullable = false) @@ -87,8 +90,23 @@ public static UserNovel create(ReadStatus status, Float userNovelRating, LocalDa return new UserNovel(status, userNovelRating, startDate, endDate, user, novel); } - public void setIsInterest(Boolean isInterest) { - this.isInterest = isInterest; + /** + * 관심 상태 지정 + */ + public void markAsInterested() { + this.isInterest = true; + } + + /** + * 관심 상태 해제 + */ + public void unmarkAsInterested() { + this.isInterest = false; + } + + public boolean isSafeToDelete() { + return !this.isInterest + && this.status == null; } public void updateUserNovel(Float userNovelRating, ReadStatus status, LocalDate startDate, LocalDate endDate) { diff --git a/src/main/java/org/websoso/WSSServer/library/repository/UserNovelRepository.java b/src/main/java/org/websoso/WSSServer/library/repository/UserNovelRepository.java index 1e367ec2..48ff0970 100644 --- a/src/main/java/org/websoso/WSSServer/library/repository/UserNovelRepository.java +++ b/src/main/java/org/websoso/WSSServer/library/repository/UserNovelRepository.java @@ -1,8 +1,10 @@ package org.websoso.WSSServer.library.repository; +import io.lettuce.core.dynamic.annotation.Param; import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import org.websoso.WSSServer.novel.domain.Novel; @@ -29,4 +31,28 @@ public interface UserNovelRepository extends JpaRepository, Use List findUserNovelByUser(User user); Optional findByNovel_NovelIdAndUser(Long novelId, User user); + + @Modifying(clearAutomatically = true) + @Query(value = """ + INSERT INTO user_novel ( + user_id, novel_id, is_interest, + user_novel_rating, status, + created_date, modified_date + ) VALUES ( + :userId, :novelId, true, + :defaultRating, + :#{#defaultStatus?.name()}, + NOW(), NOW() + ) + ON DUPLICATE KEY UPDATE + is_interest = true, + modified_date = NOW() + """, nativeQuery = true) + void upsertInterest( + @Param("userId") Long userId, + @Param("novelId") Long novelId, + @Param("defaultRating") Float defaultRating, + @Param("defaultStatus") ReadStatus defaultStatus + ); + } diff --git a/src/main/java/org/websoso/WSSServer/library/service/LibraryService.java b/src/main/java/org/websoso/WSSServer/library/service/LibraryService.java index aebeb9f0..784c48c4 100644 --- a/src/main/java/org/websoso/WSSServer/library/service/LibraryService.java +++ b/src/main/java/org/websoso/WSSServer/library/service/LibraryService.java @@ -44,6 +44,15 @@ public UserNovel getLibraryOrNull(User user, Novel novel) { return userNovelRepository.findByNovel_NovelIdAndUser(novel.getNovelId(), user).orElse(null); } + @Transactional(readOnly = true) + public UserNovel getLibraryOrNull(User user, long novelId) { + if (user == null) { + return null; + } + + return userNovelRepository.findByNovel_NovelIdAndUser(novelId, user).orElse(null); + } + @Transactional public UserNovel createLibrary(ReadStatus status, Float userNovelRating, LocalDate startDate, LocalDate endDate, User user, Novel novel) { @@ -56,6 +65,43 @@ public UserNovel createLibrary(ReadStatus status, Float userNovelRating, LocalDa novel)); } + /** + *

관심있어요를 등록한다.

+ * 서재 내역이 없다면, 서재 내역을 생성하면서 등록한다. + * + * @param user 사용자 Entity + * @param novel 서재 Entity + */ + @Transactional + public void registerInterest(User user, Novel novel) { + userNovelRepository.upsertInterest( + user.getUserId(), + novel.getNovelId(), + UserNovel.DEFAULT_RATING, + UserNovel.DEFAULT_STATUS + ); + } + + /** + *

관심있어요를 해제한다.

+ * 만약, 서재 정보가 없다면 삭제한다. + * + * @param library 서재 Entity + */ + @Transactional + public void unregisterInterest(UserNovel library) { + if (Boolean.FALSE.equals(library.getIsInterest())) { + return; + } + + library.unmarkAsInterested(); + + if (library.isSafeToDelete()) { + userNovelRepository.delete(library); + } + } + + @Transactional public void delete(UserNovel library) { userNovelRepository.delete(library); } diff --git a/src/main/java/org/websoso/WSSServer/novel/service/GenreServiceImpl.java b/src/main/java/org/websoso/WSSServer/novel/service/GenreServiceImpl.java index a5b0bb24..69e3272a 100644 --- a/src/main/java/org/websoso/WSSServer/novel/service/GenreServiceImpl.java +++ b/src/main/java/org/websoso/WSSServer/novel/service/GenreServiceImpl.java @@ -32,7 +32,7 @@ public List getGenresOrException(List names) { List uniqueNames = names.stream().distinct().toList(); - List genres = genreRepository.findByNameIn(uniqueNames); + List genres = genreRepository.findByGenreNameIn(uniqueNames); if (genres.size() != uniqueNames.size()) { throw new CustomGenreException(GENRE_NOT_FOUND, diff --git a/src/main/java/org/websoso/WSSServer/repository/GenreRepository.java b/src/main/java/org/websoso/WSSServer/repository/GenreRepository.java index 6facddcc..b06e6724 100644 --- a/src/main/java/org/websoso/WSSServer/repository/GenreRepository.java +++ b/src/main/java/org/websoso/WSSServer/repository/GenreRepository.java @@ -11,5 +11,5 @@ public interface GenreRepository extends JpaRepository { Optional findByGenreName(String name); - List findByNameIn(List names); + List findByGenreNameIn(List genreNames); }