Вступление
Добро пожаловать в часть 2 создания клона Reddit с использованием Spring Boot и React.
В части 1 мы инициализировали наш проект и добавили все необходимые зависимости. В этой статье мы рассмотрим создание всех сущностей и репозиториев, которые нам понадобятся для завершения нашего бэкенда!
Важные ссылки
- Внутренний источник: https://github.com/MaxiCB/vox-nobis/tree/master/backend
- Источник интерфейса: https://github.com/MaxiCB/vox-nobis/tree/master/client
- Прямой URL-АДРЕС: в процессе
Часть 1. Создание сущностей Домена 📝
Давайте рассмотрим все различные доменные сущности, которые будут иметь наше приложение. Внутри com.your-name.backend создайте новый пакет под названием модели и добавьте следующие классы.
Примечание: Мы установили Lombok в качестве зависимости в части 1. Мы будем использовать различные аннотации Ломбока на протяжении всего процесса разработки. Чтобы получить доступ к этим аннотациям, вам необходимо включить обработку аннотаций в вашей среде разработки. Для получения дополнительных инструкций по этому вопросу вы можете ознакомиться с руководством по настройке Ломбока здесь – Для получения дополнительных инструкций по этому вопросу вы можете ознакомиться с руководством по настройке Ломбока здесь –
Примечание: В некоторых случаях вам может потребоваться добавить следующую зависимость к вашему pom.xml файл для проверки поля
org.springframework.boot spring-boot-starter-validation
- Пользователь: Иметь уникальный идентификатор пользователя, имя пользователя, пароль, адрес электронной почты, дату создания, статус учетной записи
package com.maxicb.backend.model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import java.time.Instant; @Data @AllArgsConstructor @NoArgsConstructor @Table(name = "users") @Entity public class User { @Id @SequenceGenerator(name = "USER_GEN", sequenceName = "SEQ_USER", allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_GEN") private Long userId; @NotBlank(message = "Username is required") private String username; @NotBlank(message = "Password is required") private String password; @Email @NotBlank(message = "Email is required") private String email; private Instant creationDate; private boolean accountStatus; }
- Сообщение: Иметь уникальный идентификатор, имя сообщения, URL, описание, количество голосов, пользователя, дату создания, субреддит
package com.maxicb.backend.model; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.lang.Nullable; import javax.persistence.*; import javax.validation.constraints.NotBlank; import java.time.Instant; @Data @AllArgsConstructor @NoArgsConstructor @Builder @Entity public class Post { @Id @SequenceGenerator(name = "POST_GEN", sequenceName = "SEQ_POST", allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "POST_GEN") private Long postId; @NotBlank(message = "Post Title is required") private String postTitle; @Nullable private String url; @Nullable @Lob private String description; private Integer voteCount; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "userId", referencedColumnName = "userId") private User user; private Instant creationDate; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "id", referencedColumnName = "id") private Subreddit subreddit; }
- Субреддит: Иметь уникальный идентификатор, имя, описание, сообщения, дату создания, пользователи
package com.maxicb.backend.model; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; import javax.validation.constraints.NotBlank; import java.time.Instant; import java.util.List; @Data @AllArgsConstructor @NoArgsConstructor @Builder @Entity public class Subreddit { @Id @SequenceGenerator(name = "SUB_GEN", sequenceName = "SEQ_SUB", allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SUB_GEN") private Long id; @NotBlank(message = "Subreddit name is required") private String name; @NotBlank(message = "Subreddit description is required") private String description; @OneToMany(fetch = FetchType.LAZY) private Listposts; private Instant creationDate; @ManyToOne(fetch = FetchType.LAZY) private User user; }
- Голосовать: Иметь уникальный идентификатор, сообщение, пользователя
package com.maxicb.backend.model; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; import javax.validation.constraints.NotNull; @Data @AllArgsConstructor @NoArgsConstructor @Builder @Entity public class Vote { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long voteId; private VoteType voteType; @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "postId", referencedColumnName = "postId") private Post post; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "userId", referencedColumnName = "userId") private User user; }
- Комментарий: Иметь уникальный идентификатор, текст, сообщение, дату создания, пользователя
package com.maxicb.backend.model; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; import javax.validation.constraints.NotEmpty; import java.time.Instant; @Data @AllArgsConstructor @NoArgsConstructor @Builder @Entity public class Comment { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long id; @NotEmpty private String text; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "postId", referencedColumnName = "postId") private Post post; private Instant creationDate; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "userId", referencedColumnName = "userId") private User user; }
- ПЕРЕЧИСЛЕНИЕ типов голосов: Повышающий голос, Понижающий голос
public enum VoteType { UPVOTE(1), DOWNVOTE(-1); VoteType(int direction) {} }
- Проверка учетной записи Токен: Иметь уникальный идентификатор, токен, пользователя, срок действия
package com.maxicb.backend.model; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; import java.time.Instant; @Data @AllArgsConstructor @NoArgsConstructor @Builder @Table(name = "token") @Entity public class AccountVerificationToken { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String token; @OneToOne(fetch = FetchType.LAZY) private User user; private Instant expirationDate; }
- Уведомление по электронной почте: тема, получатель, тело
package com.maxicb.backend.model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class NotificationEmail { private String subject; private String recepient; private String body; }
Часть 2. Создание репозиториев 👩
Теперь нам нужно охватить репозитории, которые будут отвечать за хранение сущностей в базе данных. Внутри com.you-name.backend создайте новый пакет под названием репозиторий и добавьте следующие интерфейсы.
- Хранилище пользователей:
package com.maxicb.backend.repository; import com.maxicb.backend.model.User; import org.springframework.data.repository.CrudRepository; import java.util.Optional; public interface UserRepository extends CrudRepository{ Optional findByUsername(String username); }
- Хранилище сообщений:
package com.maxicb.backend.repository; import com.maxicb.backend.model.Post; import com.maxicb.backend.model.Subreddit; import com.maxicb.backend.model.User; import org.springframework.data.repository.CrudRepository; import java.util.List; public interface PostRepository extends CrudRepository{ List findAllBySubreddit(Subreddit subreddit); List findByUser(User user); }
- Репозиторий субреддитов:
package com.maxicb.backend.repository; import com.maxicb.backend.model.Subreddit; import org.springframework.data.repository.CrudRepository; import java.util.Optional; public interface SubredditRepository extends CrudRepository{ Optional findByName(String subredditName); }
- Хранилище голосов:
package com.maxicb.backend.repository; import com.maxicb.backend.model.Post; import com.maxicb.backend.model.User; import com.maxicb.backend.model.Vote; import org.springframework.data.repository.CrudRepository; import java.util.Optional; public interface VoteRepository extends CrudRepository{ Optional findTopByPostAndUserOrderByVoteIdDesc(Post post, User currentUser); }
- Хранилище комментариев:
package com.maxicb.backend.repository; import com.maxicb.backend.model.Comment; import com.maxicb.backend.model.Post; import com.maxicb.backend.model.User; import org.springframework.data.repository.CrudRepository; import java.util.List; public interface CommentRepository extends CrudRepository{ List findByPost(Post post); List findAllByUser(User user); }
- Хранилище токенов:
package com.maxicb.backend.repository; import com.maxicb.backend.model.AccountVerificationToken; import org.springframework.data.repository.CrudRepository; import java.util.Optional; public interface TokenRepository extends CrudRepository{ Optional findByToken(String token); }
Вывод 🔍
- Чтобы убедиться, что все настроено правильно, вы можете запустить приложение и убедиться, что в консоли нет ошибок. В нижней части консоли вы должны увидеть вывод, аналогичный приведенному ниже
- В этой статье мы создали сущности и репозитории, необходимые в нашем бэкэнде Spring Boot. Закладывая основу для всей логики, которая последует за этим.
Следующий
Часть 3 Реализация регистрации, отправки электронной почты и активации/верификации учетной записи.
Оригинал: “https://dev.to/maxicb/full-stack-reddit-clone-spring-boot-react-electron-app-part-2-446l”