본문 바로가기

Java/Spring

[Spring] 게시판 만들기 #1

What to do?

Entity 설계하기

게시판 서비스에 필요한 Entity 정의하기

  • User - 유저
  • Article - 게시글
  • Comment - 댓글

AuditingFields

 

다음 필드들을 모든 Entity에 공통적으로 넣을 필드다.

그래서 추상 클래스로 정의하고, 다른 Entity에서 상속받아서 사용하도록 하였다.

  • createAt - 생성한 시간
  • createBy - 생성한 사람
  • modifiedAt - 수정한 시간
  • modfiedBy - 수정한 사람
@Getter
@ToString
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class AuditingFields {
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) @CreatedDate @Column(updatable = false)
    protected LocalDateTime createdAt;

    @CreatedBy @Column(updatable = false, length = 100)
    protected String createdBy;

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) @LastModifiedDate
    protected LocalDateTime modifiedAt;

    @LastModifiedBy @Column(length = 100)
    protected String modifiedBy;
}

Jpa Configuration

 

Jpa Auditing 기능을 위한 설정을 Bean으로 만들었다.

일단은 createdBy와 modfiedBy에 "karma"가 auditing 되도록 했다.

(인증기능 구현 후에 수정해주도록 하자.)

@EnableJpaAuditing
@Configuration
public class JpaConfig {
    @Bean
    public AuditorAware<String> auditorAware() {
        // TODO
        return () -> Optional.of("karma");
    }
}

User

 

User라는 이름으로 class를 만들면, 테이블이 user라는 이름으로 만들려고 해서 에러가 난다.

그래서 UserAccount라는 이름으로 class를 작명해주었다.

  • email
  • username
  • password
  • description
  • roleType :  권한
@Getter
@Entity
@ToString
@Table(indexes = {
        @Index(columnList = "email", unique = true),
        @Index(columnList = "username", unique = true),
        @Index(columnList = "createdAt")
})
public class UserAccount {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(unique = true, length = 100) @Setter
    private String email;
    @Column(nullable = false, unique = true, length = 100) @Setter
    private String username;
    @Column(nullable = false, length = 100) @Setter
    private String password;
    @Column @Setter
    private String description;

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) @CreatedDate
    @Column(nullable = false, updatable = false)
    private LocalDateTime createdAt = LocalDateTime.now();

    @Column
    private RoleType roleType = RoleType.USER;

    protected UserAccount(){}

    private UserAccount(String email, String username, String password, String description, RoleType roleType) {
        this.email = email;
        this.username = username;
        this.password = password;
        this.description = description;
        this.roleType = roleType;
    }

    public static UserAccount of(String email, String username, String password, String description, RoleType roleType){
        return new UserAccount(email, username, password, description, roleType);
    }

    public static UserAccountDto to(UserAccount userAccount){
        return UserAccountDto.of(
                userAccount.getEmail(),
                userAccount.getUsername(),
                userAccount.getPassword(),
                userAccount.getDescription(),
                userAccount.getRoleType()
        );
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserAccount that = (UserAccount) o;
        return id.equals(that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

 

Role Type

@Getter
@AllArgsConstructor
public enum RoleType {
    USER("ROLE_USER"), MANAGER("ROLE_MANAGER"), ADMIN("ROLE_ADMIN");
    private String name;
}

Article

 

  • title : 제목
  • content : 본문
  • hashtags : 해쉬태그
  • comments : 댓글
@Getter
@Entity
@ToString
@Table(indexes = {
        @Index(columnList = "title"),
        @Index(columnList = "createdAt"),
        @Index(columnList = "createdBy")
})
@EntityListeners(AuditingFields.class)
public class Article extends AuditingFields{
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column @Setter
    private String title;
    @Column(nullable = false, length = 10000) @Setter
    private String content;
    @Column @Setter
    private String hashtags;

    @ToString.Exclude @OrderBy("id") @OneToMany(mappedBy = "article", cascade = CascadeType.ALL)
    private final Set<Comment> comments = new LinkedHashSet<>();

    protected Article(){}

    public Article(String title, String content, String hashtags) {
        this.title = title;
        this.content = content;
        this.hashtags = hashtags;
    }

    public static Article of(String title, String content, String hashtags){
        return new Article(title, content, hashtags);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Article that = (Article) o;
        return id.equals(that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

Comment

 

  • article : 게시글
  • content : 댓글
@Getter
@Entity
@ToString
@Table(indexes = {
        @Index(columnList = "createdAt"),
        @Index(columnList = "createdBy")
})
@EntityListeners(AuditingFields.class)
public class Comment extends AuditingFields{
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne(optional = false) @Setter
    private Article article;
    @Setter @Column(nullable = false, length = 1000)
    private String content;

    protected Comment(){}

    private Comment(Article article, String content) {
        this.article = article;
        this.content = content;
    }

    public static Comment of(Article article, String content){
        return new Comment(article, content);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Comment comment = (Comment) o;
        return id.equals(comment.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

 

양방향 바인딩

 

Article 한개에 여러개의 Comment가 달릴 수 있다.

그래서 양방향 Binding을 하였다.

 

  • Article
    • @OneToMany
@ToString.Exclude @OrderBy("id") @OneToMany(mappedBy = "article", cascade = CascadeType.ALL)
private final Set<Comment> comments = new LinkedHashSet<>();

 

  • Comment
    • @ManyToOne
@ManyToOne(optional = false) @Setter
private Article article;

 

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

[Spring] 게시판 만들기 #2  (0) 2022.11.13
[Tableau] Plot #2  (0) 2022.11.10
[Spring] 길찾기 서비스 #4  (0) 2022.11.06
[Spring] 길찾기 서비스 #3  (0) 2022.11.05
[Spring] 길찾기 서비스 #2  (0) 2022.11.05