Рубрики
Без рубрики

Полный клон Reddit с полным стеком – Приложение Spring Boot, React, Electron – Часть 2

Полный клон Reddit с полным стеком – Приложение Spring Boot, React, Electron – Введение в Часть 2… Помечено как react, java, веб-разработчик, машинопись.

Вступление

Добро пожаловать в часть 2 создания клона Reddit с использованием Spring Boot и React.

В части 1 мы инициализировали наш проект и добавили все необходимые зависимости. В этой статье мы рассмотрим создание всех сущностей и репозиториев, которые нам понадобятся для завершения нашего бэкенда!

Важные ссылки

Часть 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 List posts;
        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”