From d21a3c1bcfdfd85cba350a4b14785057f2978796 Mon Sep 17 00:00:00 2001 From: Just Roma Date: Fri, 28 Feb 2025 12:15:50 +0500 Subject: [PATCH 1/9] Sprint 12 add work H2 for Film --- pom.xml | 13 + .../filmorate/controller/FilmController.java | 2 +- .../filmorate/mapper/FilmMapper.java | 47 +++ .../practicum/filmorate/model/Film.java | 7 +- .../practicum/filmorate/model/Genre.java | 15 + .../practicum/filmorate/model/MpaRating.java | 15 + .../practicum/filmorate/model/User.java | 1 + .../filmorate/service/FilmService.java | 24 +- .../filmorate/service/UserService.java | 24 +- .../filmorate/storage/film/FilmDbStorage.java | 279 ++++++++++++++++++ .../filmorate/storage/film/FilmStorage.java | 2 +- .../storage/film/InMemoryFilmStorage.java | 12 +- .../filmorate/storage/user/UserDbStorage.java | 57 ++++ src/main/resources/application.properties | 10 + src/main/resources/data.sql | 16 + src/main/resources/schema.sql | 62 ++++ 16 files changed, 557 insertions(+), 29 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/mapper/FilmMapper.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/model/Genre.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/model/MpaRating.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java create mode 100644 src/main/resources/data.sql create mode 100644 src/main/resources/schema.sql diff --git a/pom.xml b/pom.xml index ba41373..3cd0ac8 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,19 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + runtime + org.zalando logbook-spring-boot-starter diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index b66662b..e00ee26 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -40,7 +40,7 @@ public Film update(@Valid @RequestBody Film filmUpdate) { } @PutMapping("/{filmId}/like/{userId}") - public Map> addLike(@PathVariable int filmId, @PathVariable int userId) { + public boolean addLike(@PathVariable int filmId, @PathVariable int userId) { return filmService.addLike(filmId, userId); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/mapper/FilmMapper.java b/src/main/java/ru/yandex/practicum/filmorate/mapper/FilmMapper.java new file mode 100644 index 0000000..c100642 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/mapper/FilmMapper.java @@ -0,0 +1,47 @@ +package ru.yandex.practicum.filmorate.mapper; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import ru.yandex.practicum.filmorate.model.Film; + +import java.time.Instant; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class FilmMapper { + + + +/* public static Film mapToUser(NewUserRequest request) { + User user = new User(); + user.setUsername(request.getUsername()); + user.setPassword(request.getPassword()); + user.setEmail(request.getEmail()); + user.setRegistrationDate(Instant.now()); + + return user; + } + + public static UserDto mapToUserDto(User user) { + UserDto dto = new UserDto(); + dto.setId(user.getId()); + dto.setUsername(user.getUsername()); + dto.setEmail(user.getEmail()); + dto.setRegistrationDate(Instant.now()); + return dto; + } + + public static User updateUserFields(User user, UpdateUserRequest request) { + if (request.hasEmail()) { + user.setEmail(request.getEmail()); + } + if (request.hasPassword()) { + user.setPassword(request.getPassword()); + } + if (request.hasUsername()) { + user.setUsername(request.getUsername()); + } + return user; + }*/ + + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index 478d9e3..5b24db5 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -8,6 +8,9 @@ import lombok.Data; import java.time.LocalDate; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; @Builder @Data @@ -23,6 +26,8 @@ public class Film { @Positive @NotNull private Integer duration; - private int likes; + private int likes_count; + List genres; + MpaRating mpa; } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java b/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java new file mode 100644 index 0000000..b691aec --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java @@ -0,0 +1,15 @@ +package ru.yandex.practicum.filmorate.model; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class Genre { + private Integer id; + @NotNull + @NotBlank + private String name; +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/MpaRating.java b/src/main/java/ru/yandex/practicum/filmorate/model/MpaRating.java new file mode 100644 index 0000000..7bf14da --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/MpaRating.java @@ -0,0 +1,15 @@ +package ru.yandex.practicum.filmorate.model; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class MpaRating { + private Integer id; + @NotNull + @NotBlank + private String name; +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index 7622f2d..e8150c8 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -25,5 +25,6 @@ public class User { @Past @NotNull private LocalDate birthday; + String friendshipStatus; } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 2c49ed0..348d2ea 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -1,42 +1,46 @@ package ru.yandex.practicum.filmorate.service; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.model.Film; -import ru.yandex.practicum.filmorate.storage.film.InMemoryFilmStorage; +import ru.yandex.practicum.filmorate.storage.film.FilmStorage; import java.util.Collection; import java.util.Map; import java.util.Set; -@RequiredArgsConstructor @Service public class FilmService { - private final InMemoryFilmStorage inMemoryFilmStorage; + private final FilmStorage filmStorage; + + public FilmService(@Qualifier("filmDbStorage")FilmStorage filmStorage) { + this.filmStorage = filmStorage; + } public Collection getAll() { - return inMemoryFilmStorage.getAll(); + return filmStorage.getAll(); } public Film create(Film film) { - return inMemoryFilmStorage.create(film); + return filmStorage.create(film); } public Film update(Film filmUpdate) { - return inMemoryFilmStorage.update(filmUpdate); + return filmStorage.update(filmUpdate); } - public Map> addLike(int filmId, int userId) { - return inMemoryFilmStorage.addLike(filmId, userId); + public boolean addLike(int filmId, int userId) { + return filmStorage.addLike(filmId, userId); } public void removeLike(int filmId, int userId) { - inMemoryFilmStorage.removeLike(filmId, userId); + filmStorage.removeLike(filmId, userId); } public Collection getFilmsByLike(Integer sizeFilms) { - return inMemoryFilmStorage.getFilmsByLike(sizeFilms); + return filmStorage.getFilmsByLike(sizeFilms); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index b6a5d6c..b5bb9ff 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -1,46 +1,50 @@ package ru.yandex.practicum.filmorate.service; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.model.User; -import ru.yandex.practicum.filmorate.storage.user.InMemoryUserStorage; +import ru.yandex.practicum.filmorate.storage.user.UserStorage; import java.util.Collection; import java.util.Map; import java.util.Set; -@RequiredArgsConstructor @Service public class UserService { - private final InMemoryUserStorage inMemoryUserStorage; + public UserService(@Qualifier("userDbStorage")UserStorage userStorage) { + this.userStorage = userStorage; + } + + private final UserStorage userStorage; public Collection getAll() { - return inMemoryUserStorage.getAll(); + return userStorage.getAll(); } public User create(User user) { - return inMemoryUserStorage.create(user); + return userStorage.create(user); } public User update(User newUser) { - return inMemoryUserStorage.update(newUser); + return userStorage.update(newUser); } public Map> addToFriend(int userId, int friendsId) { - return inMemoryUserStorage.addToFriend(userId, friendsId); + return userStorage.addToFriend(userId, friendsId); } public void removeFriend(int userId, int friendsId) { - inMemoryUserStorage.removeFriend(userId, friendsId); + userStorage.removeFriend(userId, friendsId); } public Collection getFriendsUser(int userId) { - return inMemoryUserStorage.getFriendsUser(userId); + return userStorage.getFriendsUser(userId); } public Collection getMutualFriends(int userId, int friendsId) { - return inMemoryUserStorage.getMutualFriends(userId, friendsId); + return userStorage.getMutualFriends(userId, friendsId); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java new file mode 100644 index 0000000..65e2ce4 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java @@ -0,0 +1,279 @@ +package ru.yandex.practicum.filmorate.storage.film; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.model.MpaRating; + +import java.sql.Date; +import java.sql.*; +import java.time.LocalDate; +import java.util.*; + +@Repository +public class FilmDbStorage implements FilmStorage { + protected final JdbcTemplate jdbc; + + public FilmDbStorage(JdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + private final LocalDate birthdayFilm = LocalDate.of(1895, 12, 28); + + private static final String GET_BY_ID = """ + SELECT + f.id AS film_id, + f.name AS film_name, + f.description, + f.release_date, + f.duration_minutes, + f.likes_count, + f.rating AS mpa_id, + COUNT(fl.user_id) AS likes_count, + COALESCE(STRING_AGG(fg.genre_id, ', '), '') AS genre_ids\s + FROM + film f + LEFT JOIN + film_like fl ON f.id = fl.film_id + LEFT JOIN + film_genre fg ON f.id = fg.film_id + WHERE f.id = ? + GROUP BY + f.id, f.name, f.description, f.release_date, f.duration_minutes, f.likes_count, f.rating; + """; + + private static final String GET_ALL = """ + SELECT\s + f.id AS film_id, + f.name AS film_name, + f.description, + f.release_date, + f.duration_minutes, + f.likes_count, + f.rating AS mpa_id, + COUNT(fl.user_id) AS likes_count, + COALESCE(STRING_AGG(fg.genre_id, ', '), '') AS genre_ids + FROM\s + film f + LEFT JOIN\s + film_like fl ON f.id = fl.film_id + LEFT JOIN\s + film_genre fg ON f.id = fg.film_id + GROUP BY\s + f.id, f.name, f.description, f.release_date, f.duration_minutes, f.likes_count, f.rating + ORDER BY\s + likes_count DESC; + """; + + private static final String GET_FILM_BY_LIKES = """ + SELECT\s + f.id AS film_id, + f.name AS film_name, + f.description, + f.release_date, + f.duration_minutes, + f.likes_count, + f.rating AS mpa_id, + COUNT(fl.user_id) AS likes_count, + COALESCE(STRING_AGG(fg.genre_id, ', '), '') AS genre_ids + FROM\s + film f + LEFT JOIN\s + film_like fl ON f.id = fl.film_id + LEFT JOIN\s + film_genre fg ON f.id = fg.film_id + GROUP BY\s + f.id, f.name, f.description, f.release_date, f.duration_minutes, f.likes_count, f.rating + ORDER BY\s + likes_count DESC + LIMIT ?; + """; + + private static final String INSERT_FILMS = "INSERT INTO film (name, description, release_date, " + + "duration_minutes, rating) VALUES (?, ?, ?, ?, ?)"; + private static final String INSERT_FILM_GENRE = "INSERT INTO film_genre (film_id, genre_id) VALUES (?, ?)"; + private static final String INSERT_LIKE = "INSERT INTO film_like (user_id, film_id) VALUES (?, ?)"; + String UPDATE_FILM = """ + UPDATE film + SET name = ?, description = ?, release_date = ?, duration_minutes = ?, rating = ? + WHERE id = ? + """; + private static final String UPDATE_FILM_GENRE = """ + UPDATE film_genre + SET film_id = ?, genre_id = ? + WHERE id = ? + """; + + private static final String DELETE_LIKE = "DELETE FROM film_like WHERE user_id = ? AND film_id = ?"; + private static final String DELETE_FILM_GENRE = "DELETE FROM film_genre WHERE film_id = ?"; + + private static final String GET_MAX_ID_MPA = "SELECT MAX(id) AS id FROM mpa;"; + private static final String GET_MAX_ID_GENRE = "SELECT MAX(id) AS id FROM genres;"; + + + @Override + public Collection getAll() { + return jdbc.query(GET_ALL, FilmDbStorage::getFilmMapper); + } + + @Override + public Film getFilmById(int id) { + return jdbc.queryForObject(GET_BY_ID, FilmDbStorage::getFilmMapper, id); + } + + @Override + public Film create(Film film) { + validateReleaseDate(film); + validateIdMpa(film.getMpa().getId()); + KeyHolder keyHolder = new GeneratedKeyHolder(); + + jdbc.update(connection -> { + PreparedStatement stmt = connection.prepareStatement(INSERT_FILMS, new String[]{"id"}); + stmt.setString(1, film.getName()); + stmt.setString(2, film.getDescription()); + stmt.setDate(3, Date.valueOf(film.getReleaseDate())); + stmt.setInt(4, film.getDuration()); + stmt.setInt(5, film.getMpa().getId()); + return stmt; + }, keyHolder); + + Integer id = Objects.requireNonNull(keyHolder.getKey()).intValue(); + film.setId(id); + + if (film.getGenres() != null) { + createGenre(film.getGenres(), id); + } + + return jdbc.queryForObject(GET_BY_ID, FilmDbStorage::getFilmMapper, id); + } + + @Override + public Film update(Film filmUpdate) { + int id = filmUpdate.getId(); + + jdbc.update(UPDATE_FILM, + filmUpdate.getName(), + filmUpdate.getDescription(), + filmUpdate.getReleaseDate(), + filmUpdate.getDuration(), + filmUpdate.getMpa().getId(), + id + ); + + if (filmUpdate.getGenres() != null) { + deleteGenre(id); + createGenre(filmUpdate.getGenres(), id); + } + return jdbc.queryForObject(GET_BY_ID, FilmDbStorage::getFilmMapper, id); + } + + @Override + public boolean addLike(int filmId, int userId) { + KeyHolder keyHolder = new GeneratedKeyHolder(); + + return jdbc.update(connection -> { + PreparedStatement stmt = connection.prepareStatement(INSERT_LIKE); + stmt.setInt(1, userId); + stmt.setInt(2, filmId); + return stmt; + }, keyHolder) > 0; + + } + + @Override + public void removeLike(Integer filmId, Integer userId) { + jdbc.update(DELETE_LIKE, userId, filmId); + } + + @Override + public Collection getFilmsByLike(Integer sizeFilms) { + return Collections.singleton(jdbc.queryForObject(GET_FILM_BY_LIKES, FilmDbStorage::getFilmMapper, sizeFilms)); + } + + private static Film getFilmMapper(ResultSet resultSet, int rowNum) throws SQLException { + Timestamp releaseDate = resultSet.getTimestamp("release_date"); + + String genreIds = resultSet.getString("genre_ids"); + List genres = new ArrayList<>(); + if (!genreIds.isEmpty()) { + String[] genreIdsArray = genreIds.split(",\\s*"); + for (String id : genreIdsArray) { + genres.add(Genre.builder() + .id(Integer.parseInt(id)) + .build()); + } + } + + return Film.builder() + .id(resultSet.getInt("film_id")) + .name(resultSet.getString("film_name")) + .description(resultSet.getString("description")) + .releaseDate(releaseDate.toLocalDateTime().toLocalDate()) + .duration(resultSet.getInt("duration_minutes")) + .likes_count(resultSet.getInt("likes_count")) + .mpa(MpaRating + .builder() + .id(resultSet.getInt("mpa_id")) + .build()) + .genres(genres) + .build(); + } + + + private static Integer getMaxIdMapper(ResultSet resultSet, int rowNum) throws SQLException { + return resultSet.getInt("id"); + } + + private void createGenre(List genre, Integer idFilm) { + for (Genre genres : genre) { + validateIdGenre(genres.getId()); + KeyHolder keyHolder = new GeneratedKeyHolder(); + + jdbc.update(connection -> { + PreparedStatement stmt2 = connection.prepareStatement(INSERT_FILM_GENRE); + stmt2.setInt(1, idFilm); + stmt2.setInt(2, genres.getId()); + return stmt2; + }, keyHolder); + } + } + + + private void validateReleaseDate(Film film) { + if (film.getReleaseDate().isBefore(birthdayFilm)) { + String msg = "дата релиза — не раньше 28 декабря 1895 года"; + throw new ValidationException(msg); + } + } + + private void validateIdMpa(Integer id) { + Integer maxId = jdbc.queryForObject(GET_MAX_ID_MPA, FilmDbStorage::getMaxIdMapper); + if (maxId == null) { + throw new NotFoundException("Таблица mpa пустая"); + } + if (id > maxId) { + throw new NotFoundException("Ваш id = " + id + " в таблице mpa не найден"); + } + } + + private void validateIdGenre(Integer id) { + Integer maxId = jdbc.queryForObject(GET_MAX_ID_GENRE, FilmDbStorage::getMaxIdMapper); + if (maxId == null) { + throw new NotFoundException("Таблица genres пустая"); + } + if (id > maxId) { + throw new NotFoundException("Ваш id = " + id + " в таблице genres не найден"); + } + } + + private void deleteGenre(Integer filmId) { + jdbc.update(DELETE_FILM_GENRE, filmId); + } + + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java index 9bca9ca..f21a5bc 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java @@ -16,7 +16,7 @@ public interface FilmStorage { Film update(Film filmUpdate); - Map> addLike(int filmId, int userId); + boolean addLike(int filmId, int userId); void removeLike(Integer filmId, Integer userId); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java index d02895f..fefc1e2 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java @@ -81,7 +81,7 @@ public Film update(Film filmUpdate) { } @Override - public Map> addLike(int filmId, int userId) { + public boolean addLike(int filmId, int userId) { inMemoryUserStorage.validateUserId(userId); validateFilmId(filmId); @@ -99,7 +99,7 @@ public Map> addLike(int filmId, int userId) { filmsLikes.put(filmId, likes); } - return Map.of(films.get(filmId), filmsLikes.get(filmId)); + return filmsLikes.get(filmId).contains(userId); } @Override @@ -121,7 +121,7 @@ public void removeLike(Integer filmId, Integer userId) { public Collection getFilmsByLike(Integer sizeFilms) { return films.values() .stream() - .sorted(Comparator.comparing(Film::getLikes).reversed()) + .sorted(Comparator.comparing(Film::getLikes_count).reversed()) .limit(sizeFilms) .collect(Collectors.toList()); } @@ -139,15 +139,15 @@ private boolean checkFilmsLikes(int id) { private void addLikeFilm(int filmId) { Film film = films.get(filmId); - film.setLikes(film.getLikes() + 1); + film.setLikes_count(film.getLikes_count() + 1); } private void removeLikeFilm(int filmId) { Film film = films.get(filmId); - int like = film.getLikes(); + int like = film.getLikes_count(); if (like != 0) { - film.setLikes(like - 1); + film.setLikes_count(like - 1); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java new file mode 100644 index 0000000..09f984b --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java @@ -0,0 +1,57 @@ +package ru.yandex.practicum.filmorate.storage.user; + +import ru.yandex.practicum.filmorate.model.User; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class UserDbStorage implements UserStorage{ + + + @Override + public Collection getAll() { + return List.of(); + } + + @Override + public User getUserById(int id) { + return null; + } + + @Override + public User create(User user) { + return null; + } + + @Override + public User update(User newUser) { + return null; + } + + @Override + public Map> addToFriend(int userId, int friendsId) { + return Map.of(); + } + + @Override + public void removeFriend(int userId, int friendsId) { + + } + + @Override + public Collection getFriendsUser(int userId) { + return List.of(); + } + + @Override + public Collection getMutualFriends(int userId, int friendsId) { + return List.of(); + } + + @Override + public void validateUserId(int id) { + + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 147f265..30433ed 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,11 @@ logging.level.org.zalando.logbook= TRACE +logging.level.org.springframework.jdbc=DEBUG + +spring.sql.init.mode=always +spring.datasource.url=jdbc:h2:file:./db/filmorate +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password + + + diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql new file mode 100644 index 0000000..385b622 --- /dev/null +++ b/src/main/resources/data.sql @@ -0,0 +1,16 @@ +MERGE INTO genres (id, title) KEY (title) +VALUES + (1, 'Комедия'), + (2, 'Драма'), + (3, 'Мультфильм'), + (4, 'Триллер'), + (5, 'Документальный'), + (6, 'Боевик'); + + MERGE INTO mpa (id, title) KEY (title) + VALUES + (1, 'G'), + (2, 'PG'), + (3, 'PG-13'), + (4, 'R'), + (5, 'NC-17'); \ No newline at end of file diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000..c3c00a0 --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,62 @@ + +CREATE TABLE IF NOT EXISTS mpa ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + title VARCHAR(100) NOT NULL UNIQUE +); + +CREATE TABLE IF NOT EXISTS film ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(60) NOT NULL, + description VARCHAR(200), + release_date DATE NOT NULL, + duration_minutes INTEGER, + likes_count INTEGER DEFAULT 0, + rating INTEGER, + FOREIGN KEY (rating) REFERENCES mpa(id) +); + +CREATE TABLE IF NOT EXISTS users ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + email VARCHAR(100) NOT NULL UNIQUE, + login VARCHAR(100) NOT NULL UNIQUE, + name VARCHAR(100), + birthday DATE NOT NULL +); + +CREATE TABLE IF NOT EXISTS genres ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + title VARCHAR(100) NOT NULL UNIQUE +); + +CREATE TABLE IF NOT EXISTS film_genre ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + film_id INTEGER NOT NULL, + genre_id INTEGER NOT NULL, + FOREIGN KEY (film_id) REFERENCES film(id) ON DELETE CASCADE, + FOREIGN KEY (genre_id) REFERENCES genres(id) ON DELETE CASCADE, + UNIQUE (film_id, genre_id) +); + + +CREATE TABLE IF NOT EXISTS film_like ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + user_id INTEGER NOT NULL, + film_id INTEGER NOT NULL, + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, + FOREIGN KEY (film_id) REFERENCES film(id) ON DELETE CASCADE, + UNIQUE (user_id, film_id) +); + + +CREATE TABLE IF NOT EXISTS friendship ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + status VARCHAR(100) NOT NULL, + first_user_id INTEGER NOT NULL, + second_user_id INTEGER NOT NULL, + FOREIGN KEY (first_user_id) REFERENCES users(id) ON DELETE CASCADE, + FOREIGN KEY (second_user_id) REFERENCES users(id) ON DELETE CASCADE, + UNIQUE (first_user_id, second_user_id), + CHECK (first_user_id <> second_user_id) +); + + From 26511c84ff9ff0703950ab479323d4b063c2c7dc Mon Sep 17 00:00:00 2001 From: Just Roma Date: Sun, 2 Mar 2025 10:34:05 +0500 Subject: [PATCH 2/9] Sprint 12 add work H2 for User & friends --- .../practicum/filmorate/model/Film.java | 2 - .../practicum/filmorate/model/Friendship.java | 18 ++ .../practicum/filmorate/model/User.java | 3 +- .../filmorate/service/FilmService.java | 5 +- .../filmorate/service/UserService.java | 3 +- .../filmorate/storage/film/FilmDbStorage.java | 6 +- .../storage/genre/GenreDbStorage.java | 4 + .../storage/mpa/MpaRatingDbStorage.java | 4 + .../storage/user/InMemoryUserStorage.java | 2 +- .../filmorate/storage/user/UserDbStorage.java | 266 +++++++++++++++++- .../filmorate/storage/user/UserStorage.java | 1 - src/main/resources/schema.sql | 5 +- 12 files changed, 288 insertions(+), 31 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/model/Friendship.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index 5b24db5..e02b3cb 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -8,9 +8,7 @@ import lombok.Data; import java.time.LocalDate; -import java.util.LinkedList; import java.util.List; -import java.util.Set; @Builder @Data diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Friendship.java b/src/main/java/ru/yandex/practicum/filmorate/model/Friendship.java new file mode 100644 index 0000000..58cab7e --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Friendship.java @@ -0,0 +1,18 @@ +package ru.yandex.practicum.filmorate.model; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class Friendship { + + @NotNull + private Integer firstUserId; + @NotNull + private Integer secondUserId; + @NotNull + private Boolean status; + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index e8150c8..244cce7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -8,6 +8,7 @@ import lombok.Data; import java.time.LocalDate; +import java.util.Set; @Builder @Data @@ -25,6 +26,6 @@ public class User { @Past @NotNull private LocalDate birthday; - String friendshipStatus; + Set friends; } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 348d2ea..995b7c6 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -1,21 +1,18 @@ package ru.yandex.practicum.filmorate.service; -import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.storage.film.FilmStorage; import java.util.Collection; -import java.util.Map; -import java.util.Set; @Service public class FilmService { private final FilmStorage filmStorage; - public FilmService(@Qualifier("filmDbStorage")FilmStorage filmStorage) { + public FilmService(@Qualifier("filmDbStorage") FilmStorage filmStorage) { this.filmStorage = filmStorage; } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index b5bb9ff..6b150c3 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -10,10 +10,11 @@ import java.util.Map; import java.util.Set; + @Service public class UserService { - public UserService(@Qualifier("userDbStorage")UserStorage userStorage) { + public UserService(@Qualifier("userDbStorage") UserStorage userStorage) { this.userStorage = userStorage; } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java index 65e2ce4..5931d58 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java @@ -103,11 +103,7 @@ public FilmDbStorage(JdbcTemplate jdbc) { SET name = ?, description = ?, release_date = ?, duration_minutes = ?, rating = ? WHERE id = ? """; - private static final String UPDATE_FILM_GENRE = """ - UPDATE film_genre - SET film_id = ?, genre_id = ? - WHERE id = ? - """; + private static final String DELETE_LIKE = "DELETE FROM film_like WHERE user_id = ? AND film_id = ?"; private static final String DELETE_FILM_GENRE = "DELETE FROM film_genre WHERE film_id = ?"; diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java new file mode 100644 index 0000000..961d36f --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java @@ -0,0 +1,4 @@ +package ru.yandex.practicum.filmorate.storage.genre; + +public class GenreDbStorage { +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java new file mode 100644 index 0000000..901c85b --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java @@ -0,0 +1,4 @@ +package ru.yandex.practicum.filmorate.storage.mpa; + +public class MpaRatingDbStorage { +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java index a91fc77..b3cb487 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java @@ -141,7 +141,7 @@ public Collection getMutualFriends(int userId, int friendsId) { return mutualFriends; } - @Override + public void validateUserId(int id) { if (!users.containsKey(id)) { throw new NotFoundException("Пользователь с id: " + id + " не найден"); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java index 09f984b..9fd5ff6 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java @@ -1,57 +1,295 @@ package ru.yandex.practicum.filmorate.storage.user; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Friendship; import ru.yandex.practicum.filmorate.model.User; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.*; +import java.util.stream.Collectors; -public class UserDbStorage implements UserStorage{ +@Repository +public class UserDbStorage implements UserStorage { + protected final JdbcTemplate jdbc; + public UserDbStorage(JdbcTemplate jdbc) { + this.jdbc = jdbc; + } + private static final String GET_EMAIL = "SELECT email FROM users WHERE email = ?;"; + private static final String GET_ID = "SELECT id FROM users WHERE id = ?;"; + private static final String INSERT_USERS = "INSERT INTO users (email, login, name, " + + "birthday) VALUES (?, ?, ?, ?)"; + private static final String INSERT_FRIENDSHIP = """ + INSERT INTO friendship (first_user_id, second_user_id, status) + VALUES (?, ?, ?) + """; + + private static final String UPDATE_STATUS_FRIENDSHIP = """ + UPDATE friendship + SET status ? + WHERE first_user_id = ?, second_user_id = ? + """; + + private static final String GET_FRIENDSHIP_BY_IDS = """ + SELECT * + FROM friendship + WHERE first_user_id = ? AND second_user_id = ?; + """; + + private static final String GET_FRIENDS_BY_ID = """ + SELECT STRING_AGG(second_user_id, ',') AS second_user_id + FROM friendship + WHERE first_user_id = ? AND status = true; + """; + +private static final String GET_MUTUAL_FRIENDS = """ + SELECT second_user_id AS friend_id + FROM friendship + WHERE first_user_id = ? + AND status = true + + INTERSECT + + SELECT second_user_id AS friend_id + FROM friendship + WHERE first_user_id = ? + AND status = true; + """; + + private static final String GET_BY_ID = "SELECT * FROM users WHERE id = ?;"; + private static final String GET_ALL = "SELECT * FROM users;"; + + String UPDATE_USERS = """ + UPDATE users + SET email = ?, login = ?, name = ?, birthday = ? + WHERE id = ? + """; + private static final String DELETE_FRIENDSHIP = """ + DELETE FROM friendship + WHERE first_user_id = ? AND second_user_id = ? + """; @Override public Collection getAll() { - return List.of(); + return jdbc.query(GET_ALL, UserDbStorage::getUserMapper); } @Override public User getUserById(int id) { - return null; + return jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, id); } @Override public User create(User user) { - return null; + cloneSearchEmail(user.getEmail()); + checkOrAddUserName(user); + KeyHolder keyHolder = new GeneratedKeyHolder(); + + jdbc.update(connection -> { + PreparedStatement stmt = connection.prepareStatement(INSERT_USERS, new String[]{"id"}); + stmt.setString(1, user.getEmail()); + stmt.setString(2, user.getLogin()); + stmt.setString(3, user.getName()); + stmt.setDate(4, Date.valueOf(user.getBirthday())); + return stmt; + }, keyHolder); + + Integer id = Objects.requireNonNull(keyHolder.getKey()).intValue(); + user.setId(id); + + if ((user.getFriends() != null)) { + Set ids = user.getFriends(); + for (Integer idFriend: ids) { + addToFriend(id, idFriend); + } + } + + return jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, id); } @Override - public User update(User newUser) { - return null; + public User update(User updateUser) { + Integer id = updateUser.getId(); + validateUserId(id); + + jdbc.update(UPDATE_USERS, + updateUser.getEmail(), + updateUser.getLogin(), + updateUser.getName(), + updateUser.getBirthday(), + id + ); + + return jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, id); } @Override public Map> addToFriend(int userId, int friendsId) { - return Map.of(); + int fd =1; + validateUserId(userId); + validateUserId(friendsId); + List friendships = jdbc.query(GET_FRIENDSHIP_BY_IDS, + UserDbStorage::getFriendshipMapper, userId, friendsId); + KeyHolder keyHolder = new GeneratedKeyHolder(); + + + if (friendships.isEmpty()) { + jdbc.update(connection -> { + PreparedStatement stmt = connection.prepareStatement(INSERT_FRIENDSHIP); + stmt.setInt(1, userId); + stmt.setInt(2, friendsId); + stmt.setBoolean(3, true); + return stmt; + }, keyHolder); + + jdbc.update(connection -> { + PreparedStatement stmt = connection.prepareStatement(INSERT_FRIENDSHIP); + stmt.setInt(1, friendsId); + stmt.setInt(2, userId); + stmt.setBoolean(3, false); + return stmt; + }, keyHolder); + } else { + Friendship friendship = friendships.getFirst(); + if (!friendship.getStatus()) { + jdbc.update(UPDATE_STATUS_FRIENDSHIP, + true, + friendship.getFirstUserId(), + friendship.getSecondUserId() + ); + } + } + + String friends = jdbc.queryForObject(GET_FRIENDS_BY_ID, String.class, userId); + Set friendIds = Arrays.stream(friends.split(",")) + .map(Integer::parseInt) + .collect(Collectors.toSet()); + User user = jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, userId); + return Map.of(user, friendIds); + } @Override public void removeFriend(int userId, int friendsId) { + validateUserId(userId); + validateUserId(friendsId); + jdbc.update(DELETE_FRIENDSHIP, userId, friendsId); } @Override public Collection getFriendsUser(int userId) { - return List.of(); + validateUserId(userId); + String friends = jdbc.queryForObject(GET_FRIENDS_BY_ID, String.class, userId); + List users = new ArrayList<>(); + + if (friends != null) { + String[] ids = friends.split(",\\s*"); + for (String id: ids) { + User user = jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, Integer.parseInt(id)); + users.add(user); + } + } + return users; } @Override public Collection getMutualFriends(int userId, int friendsId) { - return List.of(); + validateUserId(userId); + validateUserId(friendsId); + + List friends = jdbc.queryForList(GET_MUTUAL_FRIENDS, Integer.class, userId, friendsId); + List users = new ArrayList<>(); + if (!friends.isEmpty()) { + for (Integer id: friends) { + User user = jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, id); + users.add(user); + } + } + return users; + + } + + + private static User getUserMapper(ResultSet resultSet, int rowNum) throws SQLException { + Timestamp birthday = resultSet.getTimestamp("birthday"); + + + return User.builder() + .id(resultSet.getInt("id")) + .email(resultSet.getString("email")) + .login(resultSet.getString("login")) + .name(resultSet.getString("name")) + .birthday(birthday.toLocalDateTime().toLocalDate()) + .build(); + } + + private static Friendship getFriendshipMapper (ResultSet resultSet, int rowNum) throws SQLException { + + return Friendship.builder() + .firstUserId(resultSet.getInt("first_user_id")) + .secondUserId(resultSet.getInt("second_user_id")) + .status(resultSet.getBoolean("status")) + .build(); + } + + + private void cloneSearchEmail(String newEmail) { + List emails = jdbc.queryForList(GET_EMAIL, String.class, newEmail); + if (!emails.isEmpty()) { + throw new ValidationException("Этот Email уже используется"); + } } - @Override public void validateUserId(int id) { + List ids = jdbc.queryForList(GET_ID, Integer.class, id); + + if (ids.isEmpty()) { + throw new NotFoundException("Пользователь с id = " + id + " не найден"); + } + } + private void checkOrAddUserName(User user) { + if (user.getName() == null) { + user.setName(user.getLogin()); + } } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java index cc4c3e9..bd19de7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java @@ -24,5 +24,4 @@ public interface UserStorage { Collection getMutualFriends(int userId, int friendsId); - void validateUserId(int id); } diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index c3c00a0..8c2d997 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -20,7 +20,8 @@ CREATE TABLE IF NOT EXISTS users ( email VARCHAR(100) NOT NULL UNIQUE, login VARCHAR(100) NOT NULL UNIQUE, name VARCHAR(100), - birthday DATE NOT NULL + birthday DATE NOT NULL, + friend_id INTEGER ); CREATE TABLE IF NOT EXISTS genres ( @@ -50,9 +51,9 @@ CREATE TABLE IF NOT EXISTS film_like ( CREATE TABLE IF NOT EXISTS friendship ( id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - status VARCHAR(100) NOT NULL, first_user_id INTEGER NOT NULL, second_user_id INTEGER NOT NULL, + status boolean NOT NULL, FOREIGN KEY (first_user_id) REFERENCES users(id) ON DELETE CASCADE, FOREIGN KEY (second_user_id) REFERENCES users(id) ON DELETE CASCADE, UNIQUE (first_user_id, second_user_id), From ae6e8143b2b7271c3d447fb9769d8f0993d191ef Mon Sep 17 00:00:00 2001 From: Just Roma Date: Sun, 2 Mar 2025 12:42:38 +0500 Subject: [PATCH 3/9] Sprint 12 add work H2 for MPA --- .../controller/MpaRatingHandler.java | 31 ++++++++++++ .../filmorate/mapper/FilmMapper.java | 47 ------------------- .../filmorate/service/MpaRatingService.java | 23 +++++++++ .../storage/genre/GenreDbStorage.java | 10 ++++ .../storage/mpa/MpaRatingDbStorage.java | 45 ++++++++++++++++++ 5 files changed, 109 insertions(+), 47 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingHandler.java delete mode 100644 src/main/java/ru/yandex/practicum/filmorate/mapper/FilmMapper.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/MpaRatingService.java diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingHandler.java b/src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingHandler.java new file mode 100644 index 0000000..f4f536a --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingHandler.java @@ -0,0 +1,31 @@ +package ru.yandex.practicum.filmorate.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import ru.yandex.practicum.filmorate.model.MpaRating; +import ru.yandex.practicum.filmorate.service.MpaRatingService; + +import java.util.Collection; + +@Slf4j +@RestController +@RequestMapping("/mpa") +@RequiredArgsConstructor +public class MpaRatingHandler { + private final MpaRatingService mpaRatingService; + + @GetMapping("/{id}") + public MpaRating getNameById(@PathVariable Integer id) { + return mpaRatingService.getNameById(id); + } + + @GetMapping + public Collection getAll() { + return mpaRatingService.getAll(); + } + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/mapper/FilmMapper.java b/src/main/java/ru/yandex/practicum/filmorate/mapper/FilmMapper.java deleted file mode 100644 index c100642..0000000 --- a/src/main/java/ru/yandex/practicum/filmorate/mapper/FilmMapper.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.yandex.practicum.filmorate.mapper; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import ru.yandex.practicum.filmorate.model.Film; - -import java.time.Instant; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class FilmMapper { - - - -/* public static Film mapToUser(NewUserRequest request) { - User user = new User(); - user.setUsername(request.getUsername()); - user.setPassword(request.getPassword()); - user.setEmail(request.getEmail()); - user.setRegistrationDate(Instant.now()); - - return user; - } - - public static UserDto mapToUserDto(User user) { - UserDto dto = new UserDto(); - dto.setId(user.getId()); - dto.setUsername(user.getUsername()); - dto.setEmail(user.getEmail()); - dto.setRegistrationDate(Instant.now()); - return dto; - } - - public static User updateUserFields(User user, UpdateUserRequest request) { - if (request.hasEmail()) { - user.setEmail(request.getEmail()); - } - if (request.hasPassword()) { - user.setPassword(request.getPassword()); - } - if (request.hasUsername()) { - user.setUsername(request.getUsername()); - } - return user; - }*/ - - -} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/MpaRatingService.java b/src/main/java/ru/yandex/practicum/filmorate/service/MpaRatingService.java new file mode 100644 index 0000000..fbe3500 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/MpaRatingService.java @@ -0,0 +1,23 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.MpaRating; +import ru.yandex.practicum.filmorate.storage.mpa.MpaRatingDbStorage; + +import java.util.Collection; + +@Service +@RequiredArgsConstructor +public class MpaRatingService { + private final MpaRatingDbStorage mpaRatingDbStorage; + + public MpaRating getNameById(Integer id) { + return mpaRatingDbStorage.getNameById(id); + } + + public Collection getAll() { + return mpaRatingDbStorage.getAll(); + } + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java index 961d36f..0c8315e 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java @@ -1,4 +1,14 @@ package ru.yandex.practicum.filmorate.storage.genre; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; + +@Repository public class GenreDbStorage { + protected final JdbcTemplate jdbc; + + + public GenreDbStorage(JdbcTemplate jdbc) { + this.jdbc = jdbc; + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java index 901c85b..ca33422 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java @@ -1,4 +1,49 @@ package ru.yandex.practicum.filmorate.storage.mpa; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.model.MpaRating; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.List; + +@Repository public class MpaRatingDbStorage { + protected final JdbcTemplate jdbc; + + public MpaRatingDbStorage(JdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + private static final String GET_BY_ID = "SELECT * FROM mpa WHERE id = ?;"; + private static final String CHECK_ID = "SELECT id FROM mpa WHERE id = ?;"; + private static final String GET_ALL = "SELECT * FROM mpa ORDER BY id ;"; + + public MpaRating getNameById(Integer id) { + validateMpaId(id); + return jdbc.queryForObject(GET_BY_ID, MpaRatingDbStorage::getMpaRatingMapper, id); + } + + public Collection getAll() { + return jdbc.query(GET_ALL, MpaRatingDbStorage::getMpaRatingMapper); + } + + + private static MpaRating getMpaRatingMapper(ResultSet resultSet, int rowNum) throws SQLException { + return MpaRating.builder() + .id(resultSet.getInt("id")) + .name(resultSet.getString("title")) + .build(); + } + + private void validateMpaId(Integer id) { + List ids = jdbc.queryForList(CHECK_ID, Integer.class, id); + if (ids.isEmpty()) { + throw new NotFoundException("id = " + id + " не найден"); + } + } + } From 643c26577d9459764520131afb4f2157f371ea6c Mon Sep 17 00:00:00 2001 From: Just Roma Date: Tue, 29 Apr 2025 20:50:35 +0500 Subject: [PATCH 4/9] Sprint 12 add all --- .../filmorate/controller/FilmController.java | 7 +- .../filmorate/controller/GenreController.java | 31 ++++ ...gHandler.java => MpaRatingController.java} | 6 +- .../filmorate/mappers/FilmRowMapper.java | 51 ++++++ .../filmorate/service/FilmService.java | 4 + .../filmorate/service/GenreService.java | 34 ++++ .../filmorate/service/MpaRatingService.java | 4 +- .../filmorate/service/UserService.java | 1 - .../filmorate/storage/film/FilmDbStorage.java | 106 +++++------ .../filmorate/storage/film/FilmStorage.java | 2 - .../storage/genre/GenreDbStorage.java | 37 +++- .../storage/mpa/MpaRatingDbStorage.java | 3 +- .../filmorate/storage/user/UserDbStorage.java | 79 +++------ .../filmorate/FilmorateApplicationTests.java | 6 +- .../storage/film/FilmDbStorageTest.java | 164 +++++++++++++++++ .../storage/genre/GenreDbStorageTest.java | 49 ++++++ .../storage/mpa/MpaRatingDbStorageTest.java | 44 +++++ .../storage/user/UserDbStorageTest.java | 165 ++++++++++++++++++ 18 files changed, 661 insertions(+), 132 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java rename src/main/java/ru/yandex/practicum/filmorate/controller/{MpaRatingHandler.java => MpaRatingController.java} (84%) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorageTest.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorageTest.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorageTest.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorageTest.java diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index e00ee26..7d6f8dd 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -8,8 +8,6 @@ import ru.yandex.practicum.filmorate.service.FilmService; import java.util.Collection; -import java.util.Map; -import java.util.Set; @Slf4j @RestController @@ -24,6 +22,11 @@ public Collection getAll() { return filmService.getAll(); } + @GetMapping("/{id}") + public Film getFilmById(@PathVariable int id) { + return filmService.getFilmById(id); + } + @GetMapping("/popular") public Collection getFilmsByLike(@RequestParam(defaultValue = "10") int sizeFilms) { return filmService.getFilmsByLike(sizeFilms); diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java new file mode 100644 index 0000000..8fbf66f --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java @@ -0,0 +1,31 @@ +package ru.yandex.practicum.filmorate.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.service.GenreService; + +import java.util.Collection; + +@Slf4j +@RestController +@RequiredArgsConstructor +public class GenreController { + + private final GenreService genreService; + + @GetMapping("/genres/{id}") + public Genre getById(@PathVariable Integer id) { + return genreService.getById(id); + } + + @GetMapping("/genres") + public Collection getAll() { + return genreService.getAll(); + } + + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingHandler.java b/src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingController.java similarity index 84% rename from src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingHandler.java rename to src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingController.java index f4f536a..cf21496 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingHandler.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/MpaRatingController.java @@ -15,12 +15,12 @@ @RestController @RequestMapping("/mpa") @RequiredArgsConstructor -public class MpaRatingHandler { +public class MpaRatingController { private final MpaRatingService mpaRatingService; @GetMapping("/{id}") - public MpaRating getNameById(@PathVariable Integer id) { - return mpaRatingService.getNameById(id); + public MpaRating getById(@PathVariable Integer id) { + return mpaRatingService.getById(id); } @GetMapping diff --git a/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java new file mode 100644 index 0000000..94a627a --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java @@ -0,0 +1,51 @@ +package ru.yandex.practicum.filmorate.mappers; + +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.storage.genre.GenreDbStorage; +import ru.yandex.practicum.filmorate.storage.mpa.MpaRatingDbStorage; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; + +@Component +public class FilmRowMapper implements RowMapper { + private final GenreDbStorage genreDbStorage; + private final MpaRatingDbStorage mpa; + + public FilmRowMapper(GenreDbStorage genreDbStorage, MpaRatingDbStorage mpa) { + this.genreDbStorage = genreDbStorage; + this.mpa = mpa; + } + + @Override + public Film mapRow(ResultSet resultSet, int rowNum) throws SQLException { + + Timestamp releaseDate = resultSet.getTimestamp("release_date"); + + String genreIds = resultSet.getString("genre_ids"); + List genres = new ArrayList<>(); + if (!genreIds.isEmpty()) { + String[] genreIdsArray = genreIds.split(",\\s*"); + for (String id : genreIdsArray) { + genres.add(genreDbStorage.getById(Integer.parseInt(id))); + } + } + + return Film.builder() + .id(resultSet.getInt("film_id")) + .name(resultSet.getString("film_name")) + .description(resultSet.getString("description")) + .releaseDate(releaseDate.toLocalDateTime().toLocalDate()) + .duration(resultSet.getInt("duration_minutes")) + .likes_count(resultSet.getInt("likes_count")) + .mpa(mpa.geById(resultSet.getInt("mpa_id"))) + .genres(genres) + .build(); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 995b7c6..c29b4f6 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -20,6 +20,10 @@ public Collection getAll() { return filmStorage.getAll(); } + public Film getFilmById(int id) { + return filmStorage.getFilmById(id); + } + public Film create(Film film) { return filmStorage.create(film); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java new file mode 100644 index 0000000..869a2ae --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java @@ -0,0 +1,34 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.storage.genre.GenreDbStorage; + +import java.util.Collection; + +@Service +@RequiredArgsConstructor +public class GenreService { + + private final GenreDbStorage genreDbStorage; + + public Genre getById(Integer id) { + return genreDbStorage.getById(id); + } + + public Collection getAll() { + return genreDbStorage.getAll(); + } + + + + + + + + + + + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/MpaRatingService.java b/src/main/java/ru/yandex/practicum/filmorate/service/MpaRatingService.java index fbe3500..efb731c 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/MpaRatingService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/MpaRatingService.java @@ -12,8 +12,8 @@ public class MpaRatingService { private final MpaRatingDbStorage mpaRatingDbStorage; - public MpaRating getNameById(Integer id) { - return mpaRatingDbStorage.getNameById(id); + public MpaRating getById(Integer id) { + return mpaRatingDbStorage.geById(id); } public Collection getAll() { diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index 6b150c3..ddedbfd 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -1,6 +1,5 @@ package ru.yandex.practicum.filmorate.service; -import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.model.User; diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java index 5931d58..92db514 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java @@ -6,21 +6,27 @@ import org.springframework.stereotype.Repository; import ru.yandex.practicum.filmorate.exception.NotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.mappers.FilmRowMapper; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.model.Genre; -import ru.yandex.practicum.filmorate.model.MpaRating; import java.sql.Date; -import java.sql.*; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.time.LocalDate; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Objects; @Repository public class FilmDbStorage implements FilmStorage { protected final JdbcTemplate jdbc; + private final FilmRowMapper rowMapper; - public FilmDbStorage(JdbcTemplate jdbc) { + public FilmDbStorage(JdbcTemplate jdbc, FilmRowMapper rowMapper) { this.jdbc = jdbc; + this.rowMapper = rowMapper; } private final LocalDate birthdayFilm = LocalDate.of(1895, 12, 28); @@ -71,26 +77,20 @@ public FilmDbStorage(JdbcTemplate jdbc) { """; private static final String GET_FILM_BY_LIKES = """ - SELECT\s + SELECT f.id AS film_id, f.name AS film_name, f.description, f.release_date, f.duration_minutes, - f.likes_count, f.rating AS mpa_id, COUNT(fl.user_id) AS likes_count, COALESCE(STRING_AGG(fg.genre_id, ', '), '') AS genre_ids - FROM\s - film f - LEFT JOIN\s - film_like fl ON f.id = fl.film_id - LEFT JOIN\s - film_genre fg ON f.id = fg.film_id - GROUP BY\s - f.id, f.name, f.description, f.release_date, f.duration_minutes, f.likes_count, f.rating - ORDER BY\s - likes_count DESC + FROM film f + LEFT JOIN film_like fl ON f.id = fl.film_id + LEFT JOIN film_genre fg ON f.id = fg.film_id + GROUP BY f.id, f.name, f.description, f.release_date, f.duration_minutes, f.likes_count, f.rating + ORDER BY likes_count DESC LIMIT ?; """; @@ -104,6 +104,13 @@ public FilmDbStorage(JdbcTemplate jdbc) { WHERE id = ? """; + private static final String CHECK_DUPLICATE_FILM_GENRE = """ + SELECT EXISTS ( + SELECT 1 + FROM film_genre + WHERE film_id = ? AND genre_id = ? + ) AS record_exists; + """; private static final String DELETE_LIKE = "DELETE FROM film_like WHERE user_id = ? AND film_id = ?"; private static final String DELETE_FILM_GENRE = "DELETE FROM film_genre WHERE film_id = ?"; @@ -114,12 +121,12 @@ public FilmDbStorage(JdbcTemplate jdbc) { @Override public Collection getAll() { - return jdbc.query(GET_ALL, FilmDbStorage::getFilmMapper); + return jdbc.query(GET_ALL, rowMapper); } @Override public Film getFilmById(int id) { - return jdbc.queryForObject(GET_BY_ID, FilmDbStorage::getFilmMapper, id); + return jdbc.queryForObject(GET_BY_ID, rowMapper, id); } @Override @@ -144,8 +151,7 @@ public Film create(Film film) { if (film.getGenres() != null) { createGenre(film.getGenres(), id); } - - return jdbc.queryForObject(GET_BY_ID, FilmDbStorage::getFilmMapper, id); + return getFilmById(id); } @Override @@ -165,7 +171,7 @@ public Film update(Film filmUpdate) { deleteGenre(id); createGenre(filmUpdate.getGenres(), id); } - return jdbc.queryForObject(GET_BY_ID, FilmDbStorage::getFilmMapper, id); + return getFilmById(id); } @Override @@ -188,54 +194,30 @@ public void removeLike(Integer filmId, Integer userId) { @Override public Collection getFilmsByLike(Integer sizeFilms) { - return Collections.singleton(jdbc.queryForObject(GET_FILM_BY_LIKES, FilmDbStorage::getFilmMapper, sizeFilms)); - } - - private static Film getFilmMapper(ResultSet resultSet, int rowNum) throws SQLException { - Timestamp releaseDate = resultSet.getTimestamp("release_date"); - - String genreIds = resultSet.getString("genre_ids"); - List genres = new ArrayList<>(); - if (!genreIds.isEmpty()) { - String[] genreIdsArray = genreIds.split(",\\s*"); - for (String id : genreIdsArray) { - genres.add(Genre.builder() - .id(Integer.parseInt(id)) - .build()); - } - } - - return Film.builder() - .id(resultSet.getInt("film_id")) - .name(resultSet.getString("film_name")) - .description(resultSet.getString("description")) - .releaseDate(releaseDate.toLocalDateTime().toLocalDate()) - .duration(resultSet.getInt("duration_minutes")) - .likes_count(resultSet.getInt("likes_count")) - .mpa(MpaRating - .builder() - .id(resultSet.getInt("mpa_id")) - .build()) - .genres(genres) - .build(); + return jdbc.query(GET_FILM_BY_LIKES, rowMapper, sizeFilms); } - private static Integer getMaxIdMapper(ResultSet resultSet, int rowNum) throws SQLException { return resultSet.getInt("id"); } + private static Boolean checkDuplicateGenre(ResultSet resultSet, int rowNum) throws SQLException { + return resultSet.getBoolean("record_exists"); + } + private void createGenre(List genre, Integer idFilm) { for (Genre genres : genre) { validateIdGenre(genres.getId()); - KeyHolder keyHolder = new GeneratedKeyHolder(); - - jdbc.update(connection -> { - PreparedStatement stmt2 = connection.prepareStatement(INSERT_FILM_GENRE); - stmt2.setInt(1, idFilm); - stmt2.setInt(2, genres.getId()); - return stmt2; - }, keyHolder); + if (!validateDuplicateGenre(idFilm, genres.getId())) { + KeyHolder keyHolder = new GeneratedKeyHolder(); + + jdbc.update(connection -> { + PreparedStatement stmt2 = connection.prepareStatement(INSERT_FILM_GENRE); + stmt2.setInt(1, idFilm); + stmt2.setInt(2, genres.getId()); + return stmt2; + }, keyHolder); + } } } @@ -267,6 +249,10 @@ private void validateIdGenre(Integer id) { } } + private Boolean validateDuplicateGenre(Integer filmId, Integer genreId) { + return jdbc.queryForObject(CHECK_DUPLICATE_FILM_GENRE, FilmDbStorage::checkDuplicateGenre, filmId, genreId); + } + private void deleteGenre(Integer filmId) { jdbc.update(DELETE_FILM_GENRE, filmId); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java index f21a5bc..576426b 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java @@ -3,8 +3,6 @@ import ru.yandex.practicum.filmorate.model.Film; import java.util.Collection; -import java.util.Map; -import java.util.Set; public interface FilmStorage { diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java index 0c8315e..f1b1b77 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java @@ -2,13 +2,48 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.model.Genre; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.List; @Repository public class GenreDbStorage { protected final JdbcTemplate jdbc; - public GenreDbStorage(JdbcTemplate jdbc) { this.jdbc = jdbc; } + + private static final String GET_BY_ID = "SELECT * FROM genres WHERE id = ?;"; + private static final String CHECK_ID = "SELECT id FROM genres WHERE id = ?;"; + private static final String GET_ALL = "SELECT * FROM genres ORDER BY id ;"; + + public Genre getById(Integer id) { + validateId(id); + return jdbc.queryForObject(GET_BY_ID, GenreDbStorage::getGenreMapper, id); + } + + public Collection getAll() { + return jdbc.query(GET_ALL, GenreDbStorage::getGenreMapper); + } + + private static Genre getGenreMapper(ResultSet resultSet, int rowNum) throws SQLException { + return Genre.builder() + .id(resultSet.getInt("id")) + .name(resultSet.getString("title")) + .build(); + } + + private void validateId(Integer id) { + List ids = jdbc.queryForList(CHECK_ID, Integer.class, id); + if (ids.isEmpty()) { + throw new NotFoundException("Жанр с id = " + id + " не найден"); + } + } + + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java index ca33422..8c6bd53 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java @@ -12,6 +12,7 @@ @Repository public class MpaRatingDbStorage { + protected final JdbcTemplate jdbc; public MpaRatingDbStorage(JdbcTemplate jdbc) { @@ -22,7 +23,7 @@ public MpaRatingDbStorage(JdbcTemplate jdbc) { private static final String CHECK_ID = "SELECT id FROM mpa WHERE id = ?;"; private static final String GET_ALL = "SELECT * FROM mpa ORDER BY id ;"; - public MpaRating getNameById(Integer id) { + public MpaRating geById(Integer id) { validateMpaId(id); return jdbc.queryForObject(GET_BY_ID, MpaRatingDbStorage::getMpaRatingMapper, id); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java index 9fd5ff6..81f1b42 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java @@ -10,10 +10,7 @@ import ru.yandex.practicum.filmorate.model.User; import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; +import java.sql.*; import java.util.*; import java.util.stream.Collectors; @@ -24,6 +21,7 @@ public class UserDbStorage implements UserStorage { public UserDbStorage(JdbcTemplate jdbc) { this.jdbc = jdbc; } + private static final String GET_EMAIL = "SELECT email FROM users WHERE email = ?;"; private static final String GET_ID = "SELECT id FROM users WHERE id = ?;"; private static final String INSERT_USERS = "INSERT INTO users (email, login, name, " + @@ -33,7 +31,7 @@ INSERT INTO friendship (first_user_id, second_user_id, status) VALUES (?, ?, ?) """; - private static final String UPDATE_STATUS_FRIENDSHIP = """ + private static final String UPDATE_STATUS_FRIENDSHIP = """ UPDATE friendship SET status ? WHERE first_user_id = ?, second_user_id = ? @@ -51,19 +49,19 @@ SELECT STRING_AGG(second_user_id, ',') AS second_user_id WHERE first_user_id = ? AND status = true; """; -private static final String GET_MUTUAL_FRIENDS = """ - SELECT second_user_id AS friend_id - FROM friendship - WHERE first_user_id = ? - AND status = true - - INTERSECT - - SELECT second_user_id AS friend_id - FROM friendship - WHERE first_user_id = ? - AND status = true; - """; + private static final String GET_MUTUAL_FRIENDS = """ + SELECT second_user_id AS friend_id + FROM friendship + WHERE first_user_id = ? + AND status = true + + INTERSECT + + SELECT second_user_id AS friend_id + FROM friendship + WHERE first_user_id = ? + AND status = true; + """; private static final String GET_BY_ID = "SELECT * FROM users WHERE id = ?;"; private static final String GET_ALL = "SELECT * FROM users;"; @@ -108,7 +106,7 @@ public User create(User user) { if ((user.getFriends() != null)) { Set ids = user.getFriends(); - for (Integer idFriend: ids) { + for (Integer idFriend : ids) { addToFriend(id, idFriend); } } @@ -134,14 +132,12 @@ public User update(User updateUser) { @Override public Map> addToFriend(int userId, int friendsId) { - int fd =1; validateUserId(userId); validateUserId(friendsId); List friendships = jdbc.query(GET_FRIENDSHIP_BY_IDS, UserDbStorage::getFriendshipMapper, userId, friendsId); KeyHolder keyHolder = new GeneratedKeyHolder(); - if (friendships.isEmpty()) { jdbc.update(connection -> { PreparedStatement stmt = connection.prepareStatement(INSERT_FRIENDSHIP); @@ -194,7 +190,7 @@ public Collection getFriendsUser(int userId) { if (friends != null) { String[] ids = friends.split(",\\s*"); - for (String id: ids) { + for (String id : ids) { User user = jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, Integer.parseInt(id)); users.add(user); } @@ -210,20 +206,17 @@ public Collection getMutualFriends(int userId, int friendsId) { List friends = jdbc.queryForList(GET_MUTUAL_FRIENDS, Integer.class, userId, friendsId); List users = new ArrayList<>(); if (!friends.isEmpty()) { - for (Integer id: friends) { + for (Integer id : friends) { User user = jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, id); users.add(user); } } return users; - } - private static User getUserMapper(ResultSet resultSet, int rowNum) throws SQLException { Timestamp birthday = resultSet.getTimestamp("birthday"); - return User.builder() .id(resultSet.getInt("id")) .email(resultSet.getString("email")) @@ -233,7 +226,7 @@ private static User getUserMapper(ResultSet resultSet, int rowNum) throws SQLExc .build(); } - private static Friendship getFriendshipMapper (ResultSet resultSet, int rowNum) throws SQLException { + private static Friendship getFriendshipMapper(ResultSet resultSet, int rowNum) throws SQLException { return Friendship.builder() .firstUserId(resultSet.getInt("first_user_id")) @@ -242,15 +235,14 @@ private static Friendship getFriendshipMapper (ResultSet resultSet, int rowNum) .build(); } - private void cloneSearchEmail(String newEmail) { List emails = jdbc.queryForList(GET_EMAIL, String.class, newEmail); if (!emails.isEmpty()) { - throw new ValidationException("Этот Email уже используется"); + throw new ValidationException("Этот Email уже используется"); } } - public void validateUserId(int id) { + private void validateUserId(int id) { List ids = jdbc.queryForList(GET_ID, Integer.class, id); if (ids.isEmpty()) { @@ -265,31 +257,4 @@ private void checkOrAddUserName(User user) { } - - - - - - - - - - - - - - - - - - - - - - - - - - - } diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java index 660412e..dc5cfdf 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java @@ -6,8 +6,8 @@ @SpringBootTest class FilmorateApplicationTests { - @Test - void contextLoads() { - } + @Test + void contextLoads() { + } } diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorageTest.java new file mode 100644 index 0000000..d735ff7 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorageTest.java @@ -0,0 +1,164 @@ +package ru.yandex.practicum.filmorate.storage.film; + +import lombok.RequiredArgsConstructor; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.context.annotation.Import; +import ru.yandex.practicum.filmorate.mappers.FilmRowMapper; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.model.MpaRating; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.genre.GenreDbStorage; +import ru.yandex.practicum.filmorate.storage.mpa.MpaRatingDbStorage; +import ru.yandex.practicum.filmorate.storage.user.UserDbStorage; + +import java.time.LocalDate; +import java.util.Collection; +import java.util.List; + +@JdbcTest +@AutoConfigureTestDatabase +@RequiredArgsConstructor(onConstructor_ = @Autowired) +@Import({FilmDbStorage.class, FilmRowMapper.class, GenreDbStorage.class, MpaRatingDbStorage.class, UserDbStorage.class}) +class FilmDbStorageTest { + + private final FilmDbStorage filmDbStorage; + private final UserDbStorage userDbStorage; + + Film film1 = Film.builder() + .name("iron man") + .description("Super description") + .releaseDate(LocalDate.of(1895, 12, 28)) + .duration(1) + .genres(List.of(Genre.builder().id(1).build())) + .mpa(MpaRating.builder().id(2).build()) + .build(); + + Film film2 = Film.builder() + .name("spider man") + .description("Super man") + .releaseDate(LocalDate.of(1896, 12, 29)) + .duration(1) + .genres(List.of(Genre.builder().id(3).build())) + .mpa(MpaRating.builder().id(4).build()) + .build(); + + User user1 = User.builder() + .email("yandex@mail.ru") + .login("turbo") + .birthday(LocalDate.of(2024, 12, 12)) + .build(); + + User user2 = User.builder() + .email("Arrange@mail.ru") + .login("Away") + .birthday(LocalDate.of(2024, 11, 11)) + .build(); + + @Test + void getAll() { +// Arrange + Film createdFilm1 = filmDbStorage.create(film1); + Film createdFilm2 = filmDbStorage.create(film2); + +// Act + Collection getAllFilms = filmDbStorage.getAll(); + +// Assert + Assertions.assertThat(getAllFilms.size()).isEqualTo(2); + Assertions.assertThat(getAllFilms).isEqualTo(List.of(createdFilm1, createdFilm2)); + } + + @Test + void getFilmById() { +// Arrange + Film createdFilm = filmDbStorage.create(film1); + +// Act + Film film = filmDbStorage.getFilmById(createdFilm.getId()); + +// Assert + Assertions.assertThat(createdFilm).isEqualTo(film); + } + + @Test + void create() { +// Act + Film createdFilm = filmDbStorage.create(film1); + +// Assert + Assertions.assertThat(createdFilm.getName()).isEqualTo("iron man"); + Assertions.assertThat(createdFilm.getDescription()).isEqualTo("Super description"); + Assertions.assertThat(createdFilm.getGenres().size()).isEqualTo(1); + Assertions.assertThat(createdFilm.getMpa().getId()).isEqualTo(2); + } + + @Test + void update() { +// Arrange + Film createdFilm = filmDbStorage.create(film1); + createdFilm.setName("The Pirates of Somalia"); + createdFilm.setDescription("tell their story"); + +// Act + Film updatedFilm = filmDbStorage.update(createdFilm); + +// Assert + Assertions.assertThat(createdFilm.getId()).isEqualTo(updatedFilm.getId()); + Assertions.assertThat(updatedFilm.getName()).isEqualTo("The Pirates of Somalia"); + Assertions.assertThat(updatedFilm.getDescription()).isEqualTo("tell their story"); + } + + @Test + void addLike() { +// Arrange + Film createdFilm = filmDbStorage.create(film1); + User createdUser = userDbStorage.create(user1); + +// Act + Boolean addLike = filmDbStorage.addLike(createdFilm.getId(), createdUser.getId()); + +// Assert + Assertions.assertThat(addLike).isEqualTo(true); + } + + @Test + void removeLike() { +// Arrange + Integer createdFilmId = filmDbStorage.create(film1).getId(); + Integer createdUserId = userDbStorage.create(user1).getId(); + Boolean addLike = filmDbStorage.addLike(createdFilmId, createdUserId); + Assertions.assertThat(addLike).isEqualTo(true); + +// Act + filmDbStorage.removeLike(createdFilmId, createdUserId); + Film film = filmDbStorage.getFilmById(createdFilmId); + +// Assert + Assertions.assertThat(film.getLikes_count()).isEqualTo(0); + } + + @Test + void getFilmsByLike() { +// Arrange + Integer createdFilmId1 = filmDbStorage.create(film1).getId(); + Integer createdFilmId2 = filmDbStorage.create(film2).getId(); + Integer createdUserId1 = userDbStorage.create(user1).getId(); + Integer createdUserId2 = userDbStorage.create(user2).getId(); + + Assertions.assertThat(filmDbStorage.addLike(createdFilmId1, createdUserId1)).isEqualTo(true); + Assertions.assertThat(filmDbStorage.addLike(createdFilmId1, createdUserId2)).isEqualTo(true); + +// Act + List filmsByLike = (List) filmDbStorage.getFilmsByLike(10); + +// Assert + Assertions.assertThat(filmsByLike.size()).isEqualTo(2); + Assertions.assertThat(filmsByLike.getFirst().getLikes_count()).isEqualTo(2); + Assertions.assertThat(filmsByLike.getLast().getLikes_count()).isEqualTo(0); + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorageTest.java new file mode 100644 index 0000000..ea10a95 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorageTest.java @@ -0,0 +1,49 @@ +package ru.yandex.practicum.filmorate.storage.genre; + +import lombok.RequiredArgsConstructor; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.context.annotation.Import; +import ru.yandex.practicum.filmorate.mappers.FilmRowMapper; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.storage.film.FilmDbStorage; +import ru.yandex.practicum.filmorate.storage.mpa.MpaRatingDbStorage; +import ru.yandex.practicum.filmorate.storage.user.UserDbStorage; + +import java.util.List; + +@JdbcTest +@AutoConfigureTestDatabase +@RequiredArgsConstructor(onConstructor_ = @Autowired) +@Import({FilmDbStorage.class, FilmRowMapper.class, GenreDbStorage.class, + MpaRatingDbStorage.class, UserDbStorage.class, GenreDbStorage.class}) +class GenreDbStorageTest { + + private final GenreDbStorage genreDbStorage; + + @Test + void getById() { +// Act + Genre genre = genreDbStorage.getById(1); + +// Assert + Assertions.assertThat(genre.getName()).isEqualTo("Комедия"); + } + + @Test + void getAll() { +// Act + List genres = (List) genreDbStorage.getAll(); + +// Assert + Assertions.assertThat(genres.get(0).getName()).isEqualTo("Комедия"); + Assertions.assertThat(genres.get(1).getName()).isEqualTo("Драма"); + Assertions.assertThat(genres.get(2).getName()).isEqualTo("Мультфильм"); + Assertions.assertThat(genres.get(3).getName()).isEqualTo("Триллер"); + Assertions.assertThat(genres.get(4).getName()).isEqualTo("Документальный"); + Assertions.assertThat(genres.get(5).getName()).isEqualTo("Боевик"); + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorageTest.java new file mode 100644 index 0000000..0669637 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorageTest.java @@ -0,0 +1,44 @@ +package ru.yandex.practicum.filmorate.storage.mpa; + +import lombok.RequiredArgsConstructor; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.context.annotation.Import; +import ru.yandex.practicum.filmorate.mappers.FilmRowMapper; +import ru.yandex.practicum.filmorate.model.MpaRating; +import ru.yandex.practicum.filmorate.storage.film.FilmDbStorage; +import ru.yandex.practicum.filmorate.storage.genre.GenreDbStorage; +import ru.yandex.practicum.filmorate.storage.user.UserDbStorage; + +import java.util.List; + +@JdbcTest +@AutoConfigureTestDatabase +@RequiredArgsConstructor(onConstructor_ = @Autowired) +@Import({FilmDbStorage.class, FilmRowMapper.class, GenreDbStorage.class, + MpaRatingDbStorage.class, UserDbStorage.class, MpaRatingDbStorage.class}) +class MpaRatingDbStorageTest { + + private final MpaRatingDbStorage mpaRatingDbStorage; + + @Test + void geById() { + MpaRating mpa = mpaRatingDbStorage.geById(1); + + Assertions.assertThat(mpa.getName()).isEqualTo("G"); + } + + @Test + void getAll() { + List ratings = (List) mpaRatingDbStorage.getAll(); + + Assertions.assertThat(ratings.get(0).getName()).isEqualTo("G"); + Assertions.assertThat(ratings.get(1).getName()).isEqualTo("PG"); + Assertions.assertThat(ratings.get(2).getName()).isEqualTo("PG-13"); + Assertions.assertThat(ratings.get(3).getName()).isEqualTo("R"); + Assertions.assertThat(ratings.get(4).getName()).isEqualTo("NC-17"); + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorageTest.java new file mode 100644 index 0000000..19cdb8f --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorageTest.java @@ -0,0 +1,165 @@ +package ru.yandex.practicum.filmorate.storage.user; + +import lombok.RequiredArgsConstructor; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.context.annotation.Import; +import ru.yandex.practicum.filmorate.mappers.FilmRowMapper; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.film.FilmDbStorage; +import ru.yandex.practicum.filmorate.storage.genre.GenreDbStorage; +import ru.yandex.practicum.filmorate.storage.mpa.MpaRatingDbStorage; + +import java.time.LocalDate; +import java.util.List; + +@JdbcTest +@AutoConfigureTestDatabase +@RequiredArgsConstructor(onConstructor_ = @Autowired) +@Import({FilmDbStorage.class, FilmRowMapper.class, GenreDbStorage.class, MpaRatingDbStorage.class, UserDbStorage.class}) +class UserDbStorageTest { + + private final UserDbStorage userDbStorage; + + User user1 = User.builder() + .email("yandex@mail.ru") + .login("turbo") + .birthday(LocalDate.of(2024, 12, 12)) + .build(); + + User user2 = User.builder() + .email("Arrange@mail.ru") + .login("Away") + .birthday(LocalDate.of(2024, 11, 11)) + .build(); + + User user3 = User.builder() + .email("bobr@mail.ru") + .login("bobr") + .birthday(LocalDate.of(2024, 11, 11)) + .build(); + + @Test + void getAll() { +// Arrange + User createdUser1 = userDbStorage.create(user1); + User createdUser2 = userDbStorage.create(user2); + +// Act + List allUsers = (List) userDbStorage.getAll(); + +// Assert + Assertions.assertThat(allUsers).isEqualTo(List.of(createdUser1, createdUser2)); + } + + @Test + void getUserById() { +// Arrange + User createdUser = userDbStorage.create(user1); + +// Act + User getUser = userDbStorage.getUserById(createdUser.getId()); + +// Assert + Assertions.assertThat(createdUser).isEqualTo(getUser); + } + + @Test + void create() { +// Act + User createdUser = userDbStorage.create(user1); + +// Assert + Assertions.assertThat(createdUser).isEqualTo(user1); + + } + + @Test + void update() { +// Arrange + User createdUser = userDbStorage.create(user1); + createdUser.setLogin("Titan"); + createdUser.setEmail("titan@mail.ru"); + +// Act + userDbStorage.update(createdUser); + User getUser = userDbStorage.getUserById(createdUser.getId()); + +// Assert + Assertions.assertThat(getUser.getLogin()).isEqualTo("Titan"); + Assertions.assertThat(getUser.getEmail()).isEqualTo("titan@mail.ru"); + } + + @Test + void addToFriend() { +// Arrange + Integer createdUserId1 = userDbStorage.create(user1).getId(); + User createdUser2 = userDbStorage.create(user2); + userDbStorage.addToFriend(createdUserId1, createdUser2.getId()); + +// Act + List firends = (List) userDbStorage.getFriendsUser(createdUserId1); + +// Assert + Assertions.assertThat(firends.size()).isEqualTo(1); + Assertions.assertThat(firends.getFirst()).isEqualTo(createdUser2); + } + + @Test + void removeFriend() { +// Arrange + Integer createdUserId1 = userDbStorage.create(user1).getId(); + User createdUser2 = userDbStorage.create(user2); + userDbStorage.addToFriend(createdUserId1, createdUser2.getId()); + List firends = (List) userDbStorage.getFriendsUser(createdUserId1); + Assertions.assertThat(firends.size()).isEqualTo(1); + Assertions.assertThat(firends.getFirst()).isEqualTo(createdUser2); + +// Act + userDbStorage.removeFriend(createdUserId1, createdUser2.getId()); + List firendsUpdate = (List) userDbStorage.getFriendsUser(createdUserId1); + +// Assert + Assertions.assertThat(firendsUpdate.size()).isEqualTo(0); + } + + @Test + void getFriendsUser() { + // Arrange + Integer createdUserId1 = userDbStorage.create(user1).getId(); + User createdUser2 = userDbStorage.create(user2); + userDbStorage.addToFriend(createdUserId1, createdUser2.getId()); + +// Act + List firends = (List) userDbStorage.getFriendsUser(createdUserId1); + +// Assert + Assertions.assertThat(firends.size()).isEqualTo(1); + Assertions.assertThat(firends.getFirst()).isEqualTo(createdUser2); + } + + @Test + void getMutualFriends() { +// Arrange + Integer userId1 = userDbStorage.create(user1).getId(); + Integer userId2 = userDbStorage.create(user2).getId(); + Integer userId3 = userDbStorage.create(user3).getId(); + + userDbStorage.addToFriend(userId1, userId2); + userDbStorage.addToFriend(userId1, userId3); + userDbStorage.addToFriend(userId2, userId3); + +// Act + List mutualFriends = (List) userDbStorage.getMutualFriends(userId1, userId2); + +// Assert + Assertions.assertThat(mutualFriends.size()).isEqualTo(1); + Assertions.assertThat(mutualFriends.getFirst()).isEqualTo(user3); + + } + + +} \ No newline at end of file From c83e45dab7b4ae58175bb0411a9e250050e29f70 Mon Sep 17 00:00:00 2001 From: Just Roma Date: Tue, 29 Apr 2025 20:52:56 +0500 Subject: [PATCH 5/9] Sprint 12 add all --- .../yandex/practicum/filmorate/mappers/FilmRowMapper.java | 2 +- .../java/ru/yandex/practicum/filmorate/model/Film.java | 2 +- .../filmorate/storage/film/InMemoryFilmStorage.java | 8 ++++---- .../filmorate/storage/film/FilmDbStorageTest.java | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java index 94a627a..2a6b12a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java +++ b/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java @@ -43,7 +43,7 @@ public Film mapRow(ResultSet resultSet, int rowNum) throws SQLException { .description(resultSet.getString("description")) .releaseDate(releaseDate.toLocalDateTime().toLocalDate()) .duration(resultSet.getInt("duration_minutes")) - .likes_count(resultSet.getInt("likes_count")) + .likesCount(resultSet.getInt("likes_count")) .mpa(mpa.geById(resultSet.getInt("mpa_id"))) .genres(genres) .build(); diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index e02b3cb..8345276 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -24,7 +24,7 @@ public class Film { @Positive @NotNull private Integer duration; - private int likes_count; + private int likesCount; List genres; MpaRating mpa; diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java index fefc1e2..e58e343 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java @@ -121,7 +121,7 @@ public void removeLike(Integer filmId, Integer userId) { public Collection getFilmsByLike(Integer sizeFilms) { return films.values() .stream() - .sorted(Comparator.comparing(Film::getLikes_count).reversed()) + .sorted(Comparator.comparing(Film::getLikesCount).reversed()) .limit(sizeFilms) .collect(Collectors.toList()); } @@ -139,15 +139,15 @@ private boolean checkFilmsLikes(int id) { private void addLikeFilm(int filmId) { Film film = films.get(filmId); - film.setLikes_count(film.getLikes_count() + 1); + film.setLikesCount(film.getLikesCount() + 1); } private void removeLikeFilm(int filmId) { Film film = films.get(filmId); - int like = film.getLikes_count(); + int like = film.getLikesCount(); if (like != 0) { - film.setLikes_count(like - 1); + film.setLikesCount(like - 1); } } diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorageTest.java index d735ff7..cdfd23e 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorageTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorageTest.java @@ -139,7 +139,7 @@ void removeLike() { Film film = filmDbStorage.getFilmById(createdFilmId); // Assert - Assertions.assertThat(film.getLikes_count()).isEqualTo(0); + Assertions.assertThat(film.getLikesCount()).isEqualTo(0); } @Test @@ -158,7 +158,7 @@ void getFilmsByLike() { // Assert Assertions.assertThat(filmsByLike.size()).isEqualTo(2); - Assertions.assertThat(filmsByLike.getFirst().getLikes_count()).isEqualTo(2); - Assertions.assertThat(filmsByLike.getLast().getLikes_count()).isEqualTo(0); + Assertions.assertThat(filmsByLike.getFirst().getLikesCount()).isEqualTo(2); + Assertions.assertThat(filmsByLike.getLast().getLikesCount()).isEqualTo(0); } } \ No newline at end of file From 200bd149e29d1d74ffd6cfe285259c991d5e1b38 Mon Sep 17 00:00:00 2001 From: Just Roma Date: Tue, 29 Apr 2025 21:00:31 +0500 Subject: [PATCH 6/9] Sprint 12 add all --- .../yandex/practicum/filmorate/storage/film/FilmDbStorage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java index 92db514..134c709 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java @@ -98,7 +98,7 @@ public FilmDbStorage(JdbcTemplate jdbc, FilmRowMapper rowMapper) { "duration_minutes, rating) VALUES (?, ?, ?, ?, ?)"; private static final String INSERT_FILM_GENRE = "INSERT INTO film_genre (film_id, genre_id) VALUES (?, ?)"; private static final String INSERT_LIKE = "INSERT INTO film_like (user_id, film_id) VALUES (?, ?)"; - String UPDATE_FILM = """ + private static final String UPDATE_FILM = """ UPDATE film SET name = ?, description = ?, release_date = ?, duration_minutes = ?, rating = ? WHERE id = ? From 5990cec264a48e31201a4206829bc94c4feb7fe8 Mon Sep 17 00:00:00 2001 From: Just Roma Date: Tue, 29 Apr 2025 21:04:03 +0500 Subject: [PATCH 7/9] Sprint 12 add all --- .../yandex/practicum/filmorate/storage/user/UserDbStorage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java index 81f1b42..f14c83c 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java @@ -66,7 +66,7 @@ SELECT STRING_AGG(second_user_id, ',') AS second_user_id private static final String GET_BY_ID = "SELECT * FROM users WHERE id = ?;"; private static final String GET_ALL = "SELECT * FROM users;"; - String UPDATE_USERS = """ + private static final String UPDATE_USERS = """ UPDATE users SET email = ?, login = ?, name = ?, birthday = ? WHERE id = ? From 3cbfef6168dc29ea53f2dd3e1b84f8557306f6b2 Mon Sep 17 00:00:00 2001 From: Just Roma Date: Tue, 29 Apr 2025 21:05:39 +0500 Subject: [PATCH 8/9] Sprint 12 add all --- .../yandex/practicum/filmorate/storage/user/UserDbStorage.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java index f14c83c..6cfdc45 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java @@ -54,9 +54,7 @@ SELECT STRING_AGG(second_user_id, ',') AS second_user_id FROM friendship WHERE first_user_id = ? AND status = true - INTERSECT - SELECT second_user_id AS friend_id FROM friendship WHERE first_user_id = ? From 91065f7026b579be2d89ebc2f1b19d7a1b954a59 Mon Sep 17 00:00:00 2001 From: Just Roma Date: Wed, 30 Apr 2025 16:59:27 +0500 Subject: [PATCH 9/9] Sprint 12 Reviewer's comments --- .../filmorate/FilmorateApplication.java | 1 + .../filmorate/controller/FilmController.java | 1 - .../filmorate/controller/GenreController.java | 1 - .../filmorate/controller/UserController.java | 1 - .../filmorate/mappers/FilmRowMapper.java | 2 - .../practicum/filmorate/model/Film.java | 5 +- .../practicum/filmorate/model/Friendship.java | 2 - .../practicum/filmorate/model/User.java | 4 +- .../filmorate/service/GenreService.java | 11 --- .../filmorate/service/UserService.java | 1 - .../filmorate/storage/film/FilmDbStorage.java | 79 +++++++++---------- .../storage/film/InMemoryFilmStorage.java | 1 - .../storage/genre/GenreDbStorage.java | 7 +- .../storage/mpa/MpaRatingDbStorage.java | 6 +- .../filmorate/storage/user/UserDbStorage.java | 24 +++--- src/main/resources/schema.sql | 3 +- 16 files changed, 61 insertions(+), 88 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java index dca451b..79171d8 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java +++ b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java @@ -5,6 +5,7 @@ @SpringBootApplication public class FilmorateApplication { + public static void main(String[] args) { SpringApplication.run(FilmorateApplication.class, args); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index 7d6f8dd..6a2ca9d 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -52,5 +52,4 @@ public void removeLike(@PathVariable int filmId, @PathVariable int userId) { filmService.removeLike(filmId, userId); } - } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java index 8fbf66f..03bc124 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java @@ -27,5 +27,4 @@ public Collection getAll() { return genreService.getAll(); } - } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 7111058..c45f494 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -54,5 +54,4 @@ public void removeFriend(@PathVariable int userId, @PathVariable int friendsId) userService.removeFriend(userId, friendsId); } - } diff --git a/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java index 2a6b12a..8a56fe8 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java +++ b/src/main/java/ru/yandex/practicum/filmorate/mappers/FilmRowMapper.java @@ -25,9 +25,7 @@ public FilmRowMapper(GenreDbStorage genreDbStorage, MpaRatingDbStorage mpa) { @Override public Film mapRow(ResultSet resultSet, int rowNum) throws SQLException { - Timestamp releaseDate = resultSet.getTimestamp("release_date"); - String genreIds = resultSet.getString("genre_ids"); List genres = new ArrayList<>(); if (!genreIds.isEmpty()) { diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index 8345276..dc00fa7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -25,7 +25,6 @@ public class Film { @NotNull private Integer duration; private int likesCount; - List genres; - MpaRating mpa; - + private List genres; + private MpaRating mpa; } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Friendship.java b/src/main/java/ru/yandex/practicum/filmorate/model/Friendship.java index 58cab7e..e107872 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Friendship.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Friendship.java @@ -7,12 +7,10 @@ @Builder @Data public class Friendship { - @NotNull private Integer firstUserId; @NotNull private Integer secondUserId; @NotNull private Boolean status; - } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index 244cce7..10266a5 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -13,7 +13,6 @@ @Builder @Data public class User { - private Integer id; @NotNull @NotBlank @@ -26,6 +25,5 @@ public class User { @Past @NotNull private LocalDate birthday; - Set friends; - + private Set friends; } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java index 869a2ae..55d5dbf 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java @@ -10,7 +10,6 @@ @Service @RequiredArgsConstructor public class GenreService { - private final GenreDbStorage genreDbStorage; public Genre getById(Integer id) { @@ -21,14 +20,4 @@ public Collection getAll() { return genreDbStorage.getAll(); } - - - - - - - - - - } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index ddedbfd..e668d29 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -47,5 +47,4 @@ public Collection getMutualFriends(int userId, int friendsId) { return userStorage.getMutualFriends(userId, friendsId); } - } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java index 134c709..7bc4487 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java @@ -31,17 +31,20 @@ public FilmDbStorage(JdbcTemplate jdbc, FilmRowMapper rowMapper) { private final LocalDate birthdayFilm = LocalDate.of(1895, 12, 28); - private static final String GET_BY_ID = """ - SELECT + private static final String GET_GENERAL = """ + SELECT f.id AS film_id, f.name AS film_name, f.description, f.release_date, f.duration_minutes, + """; + + private static final String GET_BY_ID = GET_GENERAL + """ f.likes_count, f.rating AS mpa_id, COUNT(fl.user_id) AS likes_count, - COALESCE(STRING_AGG(fg.genre_id, ', '), '') AS genre_ids\s + COALESCE(STRING_AGG(fg.genre_id, ', '), '') AS genre_ids FROM film f LEFT JOIN @@ -53,36 +56,24 @@ public FilmDbStorage(JdbcTemplate jdbc, FilmRowMapper rowMapper) { f.id, f.name, f.description, f.release_date, f.duration_minutes, f.likes_count, f.rating; """; - private static final String GET_ALL = """ - SELECT\s - f.id AS film_id, - f.name AS film_name, - f.description, - f.release_date, - f.duration_minutes, + private static final String GET_ALL = GET_GENERAL + """ f.likes_count, f.rating AS mpa_id, COUNT(fl.user_id) AS likes_count, COALESCE(STRING_AGG(fg.genre_id, ', '), '') AS genre_ids - FROM\s + FROM film f - LEFT JOIN\s + LEFT JOIN film_like fl ON f.id = fl.film_id - LEFT JOIN\s + LEFT JOIN film_genre fg ON f.id = fg.film_id - GROUP BY\s + GROUP BY f.id, f.name, f.description, f.release_date, f.duration_minutes, f.likes_count, f.rating - ORDER BY\s + ORDER BY likes_count DESC; """; - private static final String GET_FILM_BY_LIKES = """ - SELECT - f.id AS film_id, - f.name AS film_name, - f.description, - f.release_date, - f.duration_minutes, + private static final String GET_FILM_BY_LIKES = GET_GENERAL + """ f.rating AS mpa_id, COUNT(fl.user_id) AS likes_count, COALESCE(STRING_AGG(fg.genre_id, ', '), '') AS genre_ids @@ -115,9 +106,20 @@ SELECT EXISTS ( private static final String DELETE_LIKE = "DELETE FROM film_like WHERE user_id = ? AND film_id = ?"; private static final String DELETE_FILM_GENRE = "DELETE FROM film_genre WHERE film_id = ?"; - private static final String GET_MAX_ID_MPA = "SELECT MAX(id) AS id FROM mpa;"; - private static final String GET_MAX_ID_GENRE = "SELECT MAX(id) AS id FROM genres;"; - + private static final String GET_MAX_ID_MPA = """ + SELECT EXISTS ( + SELECT 1 + FROM mpa + WHERE id = ? + ) AS id_exists; + """; + private static final String GET_MAX_ID_GENRE = """ + SELECT EXISTS ( + SELECT 1 + FROM genres + WHERE id = ? + ) AS id_exists; + """; @Override public Collection getAll() { @@ -184,7 +186,6 @@ public boolean addLike(int filmId, int userId) { stmt.setInt(2, filmId); return stmt; }, keyHolder) > 0; - } @Override @@ -197,11 +198,11 @@ public Collection getFilmsByLike(Integer sizeFilms) { return jdbc.query(GET_FILM_BY_LIKES, rowMapper, sizeFilms); } - private static Integer getMaxIdMapper(ResultSet resultSet, int rowNum) throws SQLException { - return resultSet.getInt("id"); + private Boolean heckIdMapper(ResultSet resultSet, int rowNum) throws SQLException { + return resultSet.getBoolean("id_exists"); } - private static Boolean checkDuplicateGenre(ResultSet resultSet, int rowNum) throws SQLException { + private Boolean checkDuplicateGenre(ResultSet resultSet, int rowNum) throws SQLException { return resultSet.getBoolean("record_exists"); } @@ -221,7 +222,6 @@ private void createGenre(List genre, Integer idFilm) { } } - private void validateReleaseDate(Film film) { if (film.getReleaseDate().isBefore(birthdayFilm)) { String msg = "дата релиза — не раньше 28 декабря 1895 года"; @@ -230,32 +230,31 @@ private void validateReleaseDate(Film film) { } private void validateIdMpa(Integer id) { - Integer maxId = jdbc.queryForObject(GET_MAX_ID_MPA, FilmDbStorage::getMaxIdMapper); - if (maxId == null) { - throw new NotFoundException("Таблица mpa пустая"); + Boolean result = jdbc.queryForObject(GET_MAX_ID_MPA, this::heckIdMapper, id); + if (result == null) { + throw new NotFoundException("Ваш id = " + id + " в таблице mpa не найден"); } - if (id > maxId) { + if (!result) { throw new NotFoundException("Ваш id = " + id + " в таблице mpa не найден"); } } private void validateIdGenre(Integer id) { - Integer maxId = jdbc.queryForObject(GET_MAX_ID_GENRE, FilmDbStorage::getMaxIdMapper); - if (maxId == null) { - throw new NotFoundException("Таблица genres пустая"); + Boolean result = jdbc.queryForObject(GET_MAX_ID_GENRE, this::heckIdMapper, id); + if (result == null) { + throw new NotFoundException("Ваш id = " + id + " в таблице genres не найден"); } - if (id > maxId) { + if (!result) { throw new NotFoundException("Ваш id = " + id + " в таблице genres не найден"); } } private Boolean validateDuplicateGenre(Integer filmId, Integer genreId) { - return jdbc.queryForObject(CHECK_DUPLICATE_FILM_GENRE, FilmDbStorage::checkDuplicateGenre, filmId, genreId); + return jdbc.queryForObject(CHECK_DUPLICATE_FILM_GENRE, this::checkDuplicateGenre, filmId, genreId); } private void deleteGenre(Integer filmId) { jdbc.update(DELETE_FILM_GENRE, filmId); } - } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java index e58e343..cad5024 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java @@ -29,7 +29,6 @@ public int getNextId() { return id++; } - @Override public Collection getAll() { log.info("GET, all films"); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java index f1b1b77..89484a7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/genre/GenreDbStorage.java @@ -24,14 +24,14 @@ public GenreDbStorage(JdbcTemplate jdbc) { public Genre getById(Integer id) { validateId(id); - return jdbc.queryForObject(GET_BY_ID, GenreDbStorage::getGenreMapper, id); + return jdbc.queryForObject(GET_BY_ID, this::getGenreMapper, id); } public Collection getAll() { - return jdbc.query(GET_ALL, GenreDbStorage::getGenreMapper); + return jdbc.query(GET_ALL, this::getGenreMapper); } - private static Genre getGenreMapper(ResultSet resultSet, int rowNum) throws SQLException { + private Genre getGenreMapper(ResultSet resultSet, int rowNum) throws SQLException { return Genre.builder() .id(resultSet.getInt("id")) .name(resultSet.getString("title")) @@ -45,5 +45,4 @@ private void validateId(Integer id) { } } - } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java index 8c6bd53..6196bee 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/mpa/MpaRatingDbStorage.java @@ -25,15 +25,15 @@ public MpaRatingDbStorage(JdbcTemplate jdbc) { public MpaRating geById(Integer id) { validateMpaId(id); - return jdbc.queryForObject(GET_BY_ID, MpaRatingDbStorage::getMpaRatingMapper, id); + return jdbc.queryForObject(GET_BY_ID, this::getMpaRatingMapper, id); } public Collection getAll() { - return jdbc.query(GET_ALL, MpaRatingDbStorage::getMpaRatingMapper); + return jdbc.query(GET_ALL, this::getMpaRatingMapper); } - private static MpaRating getMpaRatingMapper(ResultSet resultSet, int rowNum) throws SQLException { + private MpaRating getMpaRatingMapper(ResultSet resultSet, int rowNum) throws SQLException { return MpaRating.builder() .id(resultSet.getInt("id")) .name(resultSet.getString("title")) diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java index 6cfdc45..cb21827 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserDbStorage.java @@ -76,12 +76,12 @@ SELECT STRING_AGG(second_user_id, ',') AS second_user_id @Override public Collection getAll() { - return jdbc.query(GET_ALL, UserDbStorage::getUserMapper); + return jdbc.query(GET_ALL, this::getUserMapper); } @Override public User getUserById(int id) { - return jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, id); + return jdbc.queryForObject(GET_BY_ID, this::getUserMapper, id); } @Override @@ -99,7 +99,7 @@ public User create(User user) { return stmt; }, keyHolder); - Integer id = Objects.requireNonNull(keyHolder.getKey()).intValue(); + int id = Objects.requireNonNull(keyHolder.getKey()).intValue(); user.setId(id); if ((user.getFriends() != null)) { @@ -109,7 +109,7 @@ public User create(User user) { } } - return jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, id); + return jdbc.queryForObject(GET_BY_ID, this::getUserMapper, id); } @Override @@ -125,15 +125,14 @@ public User update(User updateUser) { id ); - return jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, id); + return jdbc.queryForObject(GET_BY_ID, this::getUserMapper, id); } @Override public Map> addToFriend(int userId, int friendsId) { validateUserId(userId); validateUserId(friendsId); - List friendships = jdbc.query(GET_FRIENDSHIP_BY_IDS, - UserDbStorage::getFriendshipMapper, userId, friendsId); + List friendships = jdbc.query(GET_FRIENDSHIP_BY_IDS, this::getFriendshipMapper, userId, friendsId); KeyHolder keyHolder = new GeneratedKeyHolder(); if (friendships.isEmpty()) { @@ -167,7 +166,7 @@ public Map> addToFriend(int userId, int friendsId) { Set friendIds = Arrays.stream(friends.split(",")) .map(Integer::parseInt) .collect(Collectors.toSet()); - User user = jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, userId); + User user = jdbc.queryForObject(GET_BY_ID, this::getUserMapper, userId); return Map.of(user, friendIds); } @@ -189,7 +188,7 @@ public Collection getFriendsUser(int userId) { if (friends != null) { String[] ids = friends.split(",\\s*"); for (String id : ids) { - User user = jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, Integer.parseInt(id)); + User user = jdbc.queryForObject(GET_BY_ID, this::getUserMapper, Integer.parseInt(id)); users.add(user); } } @@ -205,14 +204,14 @@ public Collection getMutualFriends(int userId, int friendsId) { List users = new ArrayList<>(); if (!friends.isEmpty()) { for (Integer id : friends) { - User user = jdbc.queryForObject(GET_BY_ID, UserDbStorage::getUserMapper, id); + User user = jdbc.queryForObject(GET_BY_ID, this::getUserMapper, id); users.add(user); } } return users; } - private static User getUserMapper(ResultSet resultSet, int rowNum) throws SQLException { + private User getUserMapper(ResultSet resultSet, int rowNum) throws SQLException { Timestamp birthday = resultSet.getTimestamp("birthday"); return User.builder() @@ -224,7 +223,7 @@ private static User getUserMapper(ResultSet resultSet, int rowNum) throws SQLExc .build(); } - private static Friendship getFriendshipMapper(ResultSet resultSet, int rowNum) throws SQLException { + private Friendship getFriendshipMapper(ResultSet resultSet, int rowNum) throws SQLException { return Friendship.builder() .firstUserId(resultSet.getInt("first_user_id")) @@ -254,5 +253,4 @@ private void checkOrAddUserName(User user) { } } - } diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 8c2d997..98b1e49 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -20,8 +20,7 @@ CREATE TABLE IF NOT EXISTS users ( email VARCHAR(100) NOT NULL UNIQUE, login VARCHAR(100) NOT NULL UNIQUE, name VARCHAR(100), - birthday DATE NOT NULL, - friend_id INTEGER + birthday DATE NOT NULL ); CREATE TABLE IF NOT EXISTS genres (