diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/ReviewController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/ReviewController.java index d0489de..a081a78 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/ReviewController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/ReviewController.java @@ -10,6 +10,7 @@ import ru.yandex.practicum.filmorate.dto.review.NewReviewRequest; import ru.yandex.practicum.filmorate.dto.review.ReviewDto; import ru.yandex.practicum.filmorate.dto.review.UpdateReviewRequest; +import ru.yandex.practicum.filmorate.model.Reaction; import ru.yandex.practicum.filmorate.service.review.ReviewService; import java.util.Collection; @@ -72,13 +73,13 @@ public void setDislike(@PathVariable @Positive long id, public void removeLike(@PathVariable @Positive long id, @PathVariable @Positive long userId) { log.trace("Remove review like by reviewId: {}, from userId: {}", id, userId); - reviewService.removeLike(id, userId); + reviewService.removeReaction(id, userId, Reaction.LIKE); } @DeleteMapping("/{id}/dislike/{userId}") public void removeDislike(@PathVariable @Positive long id, @PathVariable @Positive long userId) { log.trace("Remove review dislike by reviewId: {}, from userId: {}", id, userId); - reviewService.removeDislike(id, userId); + reviewService.removeReaction(id, userId, Reaction.DISLIKE); } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Reaction.java b/src/main/java/ru/yandex/practicum/filmorate/model/Reaction.java new file mode 100644 index 0000000..a7b7603 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Reaction.java @@ -0,0 +1,5 @@ +package ru.yandex.practicum.filmorate.model; + +public enum Reaction { + LIKE, DISLIKE +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/repository/review/JdbcReviewRepository.java b/src/main/java/ru/yandex/practicum/filmorate/repository/review/JdbcReviewRepository.java index 8bbb5bc..4df544b 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/repository/review/JdbcReviewRepository.java +++ b/src/main/java/ru/yandex/practicum/filmorate/repository/review/JdbcReviewRepository.java @@ -6,6 +6,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.model.Reaction; import ru.yandex.practicum.filmorate.model.Review; import java.util.Collection; @@ -25,10 +26,6 @@ public class JdbcReviewRepository implements ReviewRepository { FROM reviews r JOIN film_reviews fr ON r.review_id = fr.review_id """; - private static final int UP_UR = 1; - private static final int DOUBLE_UP_UR = 2; - private static final int DROP_UR = -1; - private static final int DOUBLE_DROP_UR = -2; private final NamedParameterJdbcOperations jdbc; private final RowMapper mapper; @@ -95,59 +92,30 @@ public Collection findAllByFilm(Long filmId, long count) { } @Override - public void setLike(long id, long userId) { + public void setReaction(long id, long userId, Reaction reaction) { MapSqlParameterSource params = new MapSqlParameterSource("review_id", id) .addValue("user_id", userId); - Boolean isPositiveYet = isPositive(params); - jdbc.update(""" - MERGE INTO review_likes (review_id, user_id, is_positive) - KEY (review_id, user_id) - VALUES (:review_id, :user_id, TRUE) - """, params); - if (isPositiveYet == null) { - changeUsefulRating(params, UP_UR); - } else if (isPositiveYet) { - changeUsefulRating(params, DOUBLE_UP_UR); + switch (reaction) { + case LIKE -> params.addValue("is_positive", true); + case DISLIKE -> params.addValue("is_positive", false); } - } - - @Override - public void setDislike(long id, long userId) { - MapSqlParameterSource params = new MapSqlParameterSource("review_id", id) - .addValue("user_id", userId); - Boolean isPositiveYet = isPositive(params); jdbc.update(""" MERGE INTO review_likes (review_id, user_id, is_positive) KEY (review_id, user_id) - VALUES (:review_id, :user_id, FALSE) - """, params); - if (isPositiveYet == null) { - changeUsefulRating(params, DROP_UR); - } else if (isPositiveYet) { - changeUsefulRating(params, DOUBLE_DROP_UR); - } - } - - @Override - public void removeLike(long id, long userId) { - MapSqlParameterSource params = new MapSqlParameterSource("review_id", id) - .addValue("user_id", userId); - jdbc.update(""" - DELETE FROM review_likes - WHERE review_id = :review_id AND user_id = :user_id + VALUES (:review_id, :user_id, :is_positive) """, params); - changeUsefulRating(params, DROP_UR); + updateUsefulRating(params); } @Override - public void removeDislike(long id, long userId) { + public void removeReaction(long id, long userId) { MapSqlParameterSource params = new MapSqlParameterSource("review_id", id) .addValue("user_id", userId); jdbc.update(""" DELETE FROM review_likes WHERE review_id = :review_id AND user_id = :user_id """, params); - changeUsefulRating(params, UP_UR); + updateUsefulRating(params); } private MapSqlParameterSource getBaseParams(Review review) { @@ -156,21 +124,15 @@ private MapSqlParameterSource getBaseParams(Review review) { .addValue("is_Positive", review.getIsPositive()); } - private Boolean isPositive(MapSqlParameterSource params) { - List list = jdbc.query(""" - SELECT is_positive - FROM review_likes - WHERE review_id = :review_id AND user_id = :user_id - """, params, (rs, rowNum) -> rs.getBoolean("is_positive")); - return list.isEmpty() ? null : list.getFirst(); - } - - private void changeUsefulRating(MapSqlParameterSource params, int points) { - params.addValue("points", points); + private void updateUsefulRating(MapSqlParameterSource params) { jdbc.update(""" - UPDATE reviews - SET useful_rating = useful_rating + :points - WHERE review_id = :review_id + UPDATE reviews r + SET useful_rating = COALESCE(( + SELECT SUM(CASE WHEN is_positive THEN 1 ELSE -1 END) + FROM review_likes rl + WHERE rl.review_id = r.review_id), + 0) + WHERE r.review_id = :review_id; """, params); } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/repository/review/ReviewRepository.java b/src/main/java/ru/yandex/practicum/filmorate/repository/review/ReviewRepository.java index e1bca95..cf91540 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/repository/review/ReviewRepository.java +++ b/src/main/java/ru/yandex/practicum/filmorate/repository/review/ReviewRepository.java @@ -1,5 +1,6 @@ package ru.yandex.practicum.filmorate.repository.review; +import ru.yandex.practicum.filmorate.model.Reaction; import ru.yandex.practicum.filmorate.model.Review; import java.util.Collection; @@ -16,11 +17,7 @@ public interface ReviewRepository { Collection findAllByFilm(Long filmId, long count); - void setLike(long id, long userId); + void setReaction(long id, long userId, Reaction reaction); - void setDislike(long id, long userId); - - void removeLike(long id, long userId); - - void removeDislike(long id, long userId); + void removeReaction(long id, long userId); } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/review/ReviewService.java b/src/main/java/ru/yandex/practicum/filmorate/service/review/ReviewService.java index 08a2212..10a346a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/review/ReviewService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/review/ReviewService.java @@ -3,6 +3,7 @@ import ru.yandex.practicum.filmorate.dto.review.NewReviewRequest; import ru.yandex.practicum.filmorate.dto.review.ReviewDto; import ru.yandex.practicum.filmorate.dto.review.UpdateReviewRequest; +import ru.yandex.practicum.filmorate.model.Reaction; import java.util.Collection; @@ -22,7 +23,5 @@ public interface ReviewService { void setDislike(long id, long userId); - void removeLike(long id, long userId); - - void removeDislike(long id, long userId); -} + void removeReaction(long id, long userId, Reaction reaction); +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/review/ReviewServiceImpl.java b/src/main/java/ru/yandex/practicum/filmorate/service/review/ReviewServiceImpl.java index d6e29b1..701cce3 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/review/ReviewServiceImpl.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/review/ReviewServiceImpl.java @@ -3,13 +3,12 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import ru.yandex.practicum.filmorate.dto.review.NewReviewRequest; -import ru.yandex.practicum.filmorate.dto.review.ReviewDto; -import ru.yandex.practicum.filmorate.dto.review.UpdateReviewRequest; +import ru.yandex.practicum.filmorate.dto.review.*; import ru.yandex.practicum.filmorate.exception.NotFoundException; import ru.yandex.practicum.filmorate.mapper.ReviewMapper; import ru.yandex.practicum.filmorate.model.EventType; import ru.yandex.practicum.filmorate.model.Operation; +import ru.yandex.practicum.filmorate.model.Reaction; import ru.yandex.practicum.filmorate.model.Review; import ru.yandex.practicum.filmorate.repository.film.FilmRepository; import ru.yandex.practicum.filmorate.repository.review.ReviewRepository; @@ -77,7 +76,7 @@ public void setLike(long id, long userId) { getReviewOrThrow(id); throwIfUserNotFound(userId); log.info("Like to review {} has been added by user {}", id, userId); - reviewRepository.setLike(id, userId); + reviewRepository.setReaction(id, userId, Reaction.LIKE); } @Override @@ -85,23 +84,18 @@ public void setDislike(long id, long userId) { getReviewOrThrow(id); throwIfUserNotFound(userId); log.info("Dislike to review {} has been added by user {}", id, userId); - reviewRepository.setDislike(id, userId); + reviewRepository.setReaction(id, userId, Reaction.DISLIKE); } @Override - public void removeLike(long id, long userId) { + public void removeReaction(long id, long userId, Reaction reaction) { getReviewOrThrow(id); throwIfUserNotFound(userId); - log.info("Like to review {} has been removed by user {}", id, userId); - reviewRepository.removeLike(id, userId); - } - - @Override - public void removeDislike(long id, long userId) { - getReviewOrThrow(id); - throwIfUserNotFound(userId); - log.info("Dislike to review {} has been removed by user {}", id, userId); - reviewRepository.removeDislike(id, userId); + switch (reaction) { + case LIKE -> log.info("Like to review {} has been removed by user {}", id, userId); + case DISLIKE -> log.info("Dislike to review {} has been removed by user {}", id, userId); + } + reviewRepository.removeReaction(id, userId); } private Review getReviewOrThrow(long id) { @@ -118,4 +112,4 @@ private void throwIfFilmNotFound(long id) { filmRepository.findById(id) .orElseThrow(NotFoundException.supplier("Film with filmId %d not found", id)); } -} +} \ No newline at end of file