본문 바로가기

Java/Spring

[Spring] 간단한 SNS 만들기 #1

What to do?

Domain 코드 작성하기

  1. User
  2. Post
  3. Comment

User

 

  • RoleType
    • 권한 설정을 위해 만든 enum
public enum RoleType {
    USER,MANAGER,ADMIN;
}

 

  • UserEntity
    • 필드
      • 아이디, 이메일, 유저명, 비밀번호, 권한, 생성시간, 수정시간, 삭제시간
    • 인증기능을 구현하기 위해서 UserDetails를 implement
      • getAuthroties, isAccountExpired, isAccountNonLocked, isCredentialsNonExpired, isEnabled 를 구현해주어야 함
@Entity
@Getter
@Setter
@Table(name = "\"user\"")
@SQLDelete(sql = "UPDATE \"user\" SET removed_at = NOW() WHERE id=?")
@EntityListeners(AuditingEntityListener.class)
@Where(clause = "removed_at is NULL")
public class UserEntity implements UserDetails {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(unique = true)
    private String email;
    @Column(unique = true)
    private String username;
    @Column(unique = true)
    private String nickname;
    private String password;
    @Enumerated(EnumType.STRING)
    private RoleType role;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) @CreatedDate @Column(updatable = false, name = "created_at")
    private LocalDateTime createdAt;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) @LastModifiedDate @Column(name = "modified_at")
    private LocalDateTime modifiedAt;
    @Column(name = "removed_at") @Setter
    private LocalDateTime removedAt;

    private UserEntity(String email, String username, String nickname, String password, RoleType role, LocalDateTime createdAt, LocalDateTime removedAt) {
        this.email = email;
        this.username = username;
        this.nickname = nickname;
        this.password = password;
        this.role = role;
        this.createdAt = createdAt;
        this.removedAt = removedAt;
    }

    protected UserEntity(){}

    public static UserEntity of(String email, String username, String nickname, String password, RoleType role, LocalDateTime createdAt, LocalDateTime removedAt) {
        return new UserEntity(email, username, nickname, password, role, createdAt, removedAt);
    }

    public static UserDto dto(UserEntity entity){
        return UserDto.of(
                entity.getEmail(),
                entity.getUsername(),
                entity.getNickname(),
                entity.getPassword(),
                entity.getRole(),
                entity.getCreatedAt(),
                entity.getRemovedAt()
        );
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Set.of(new SimpleGrantedAuthority(role.name()));
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

 

  • UserDto
@Getter
public class UserDto {
    private String email;
    private String username;
    private String nickname;
    private String password;
    private RoleType role;
    private LocalDateTime createdAt;
    private LocalDateTime removedAt;

    private UserDto(String email, String username, String nickname, String password, RoleType role, LocalDateTime createdAt, LocalDateTime removedAt) {
        this.email = email;
        this.username = username;
        this.nickname = nickname;
        this.password = password;
        this.role = role;
        this.createdAt = createdAt;
        this.removedAt = removedAt;
    }

    protected UserDto(){}

    public static UserDto of(String email, String username, String nickname, String password, RoleType role, LocalDateTime createdAt, LocalDateTime removedAt) {
        return new UserDto(email,username,nickname,password,role,createdAt,removedAt);
    }
}

 

포스팅

 

  • 메타데이터
    • 생성시간, 수정시간, 생성한사람, 수정한사람, 삭제시간 같은 경우 자동으로 Auditing되도록 하고 싶음
    • Auditing이 필요한 필드들을 abstract class로 구현
@Getter
@ToString
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class AuditingFields {
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) @CreatedDate @Column(updatable = false, name = "created_at")
    private LocalDateTime createdAt;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) @LastModifiedDate @Column(name = "modified_at")
    private LocalDateTime modifiedAt;
    @CreatedBy @Column(updatable = false, length = 100, name = "created_by")
    private String createdBy;
    @LastModifiedBy @Column(length = 100, name = "modified_by")
    private String modifiedBy;
    @Column(name = "removed_at") @Setter
    private LocalDateTime removedAt;
}

 

createdBy나 modfiedBy와 같은 컬럼은 인증기능 구현이 되야 auditing이 가능함

인증기능 구현 후 아래와 같이 JpaConfig를 넣어주면 auditing이 됨

@EnableJpaAuditing
@Configuration
public class JpaConfig {
    @Bean
    public AuditorAware<String> auditorAware() {
        return () -> Optional.of(SecurityContextHolder.getContext())
                .map(SecurityContext::getAuthentication)
                .filter(Authentication::isAuthenticated)
                .map(Authentication::getName);
    }
}

 

  • PostEntity
    • 필드 : 제목, 본문, 유저, 댓글
    • @ManyToOne : 포스팅과 유저는 다대일 관계
    • @OneToMany : 포스팅과 댓글은 일대다 관계
@Setter
@Getter
@Entity
@Table(name = "\"post\"")
@SQLDelete(sql = "UPDATE \"post\" SET removed_at = NOW() WHERE id=?")
@Where(clause = "removed_at is NULL")
public class PostEntity extends AuditingFields {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "title", nullable = false)
    private String title;
    @Column(name = "content", columnDefinition = "TEXT", nullable = false)
    private String content;
    @ManyToOne @JoinColumn(name = "user_id")
    private UserEntity user;
    @OneToMany(fetch = FetchType.LAZY) @JoinColumn(name = "post_id")
    private List<CommentEntity> comments;

    private PostEntity(String title, String content, UserEntity user, List<CommentEntity> comments) {
        this.title = title;
        this.content = content;
        this.user = user;
        this.comments = comments;
    }

    protected PostEntity(){}

    public static PostEntity of(String title, String content, UserEntity user) {
        return new PostEntity(title, content, user, List.of());
    }

    public static PostDto dto(PostEntity entity){
        return PostDto.of(
                entity.getId(),
                entity.getTitle(),
                entity.getContent(),
                entity.getUser().getNickname(),
                entity.getCreatedAt(),
                entity.getModifiedAt(),
                entity.getCreatedBy(),
                entity.getModifiedBy()
        );
    }
}

 

  • PostDto
@Getter
@Setter
public class PostDto {
    private Long id;
    private String title;
    private String content;
    private String nickname;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;
    private String createdBy;
    private String modifiedBy;

    private PostDto(Long id, String title, String content, String nickname, LocalDateTime createdAt, LocalDateTime modifiedAt, String createdBy, String modifiedBy) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.nickname = nickname;
        this.createdAt = createdAt;
        this.modifiedAt = modifiedAt;
        this.createdBy = createdBy;
        this.modifiedBy = modifiedBy;
    }

    protected PostDto(){}

    public static PostDto of(Long id, String title, String content, String nickname, LocalDateTime createdAt, LocalDateTime modifiedAt, String createdBy, String modifiedBy) {
        return new PostDto(id, title, content, nickname, createdAt, modifiedAt, createdBy, modifiedBy);
    }
}

댓글

 

  • CommentEntity
    • @ManyToOne
      • 댓글과 유저는 다대일 관계
      • 댓글과 포스팅은 다대일 관계
@Getter
@Setter
@Table(name = "\"comment\"")
@Entity
public class CommentEntity extends AuditingFields {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "content")
    private String content;
    @ManyToOne @JoinColumn(name = "user_id")
    private UserEntity user;
    @ManyToOne @JoinColumn(name = "post_id")
    private PostEntity post;

    private CommentEntity(String content, UserEntity user, PostEntity post) {
        this.content = content;
        this.user = user;
        this.post = post;
    }

    protected CommentEntity(){}

    public static CommentEntity of(String content, UserEntity user, PostEntity post){
        return new CommentEntity(content, user, post);
    }

    public static CommentDto dto(CommentEntity entity){
        return CommentDto.of(
                entity.getId(),
                entity.getPost().getId(),
                entity.getContent(),
                entity.getUser().getNickname(),
                entity.getCreatedAt(),
                entity.getModifiedAt(),
                entity.getCreatedBy(),
                entity.getModifiedBy()
        );
    }
}

 

  • CommentDto
@Getter
@Setter
public class CommentDto {
    private Long id;
    private Long postId;
    private String content;
    private String nickname;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;
    private String createdBy;
    private String modifiedBy;

    private CommentDto(Long id, Long postId, String content, String nickname, LocalDateTime createdAt, LocalDateTime modifiedAt, String createdBy, String modifiedBy) {
        this.id = id;
        this.postId = postId;
        this.content = content;
        this.nickname = nickname;
        this.createdAt = createdAt;
        this.modifiedAt = modifiedAt;
        this.createdBy = createdBy;
        this.modifiedBy = modifiedBy;
    }

    protected CommentDto(){}

    public static CommentDto of(Long id, Long postId, String content, String nickname, LocalDateTime createdAt, LocalDateTime modifiedAt, String createdBy, String modifiedBy){
        return new CommentDto(id,postId,content,nickname,createdAt,modifiedAt, createdBy, modifiedBy);
    }
}

 

'Java > Spring' 카테고리의 다른 글

[Spring] 간단한 SNS 만들기 #3  (0) 2022.12.22
[Spring] 간단한 SNS 만들기 #2  (0) 2022.12.22
[Spring] 길찾기 서비스 #6  (0) 2022.12.11
[Spring] 길찾기 서비스 #5  (0) 2022.12.11
[Spring] 게시판 만들기 #12  (0) 2022.11.26