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를 작명해주었다.
- 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 |