ERD

Entity 설계
- 회원 (USERS)
- user_id : PK 자동생성
- name : 회원 이름
- email : 회원 이메일
- password : 비밀번호
- joined_date : 가입 날짜
- 게시글 (BOARDS)
- board_id : PK 자동생성
- user_id : FK 회원 아이디
- title : 게시글 제목
- board_comment : 게시글 내용
- created_at : 작성 일자
- 댓글 (COMMENTS)
- comment_id : PK 자동생성
- board_id : FK 게시글 아이디
- user_id : FK 회원 아이디
- comment_content : 댓글 내용
- created_at : 작성 일자
연관관계 매핑
- 회원 - 게시글 (일대다)
- 회원 - 댓글 (일대다)
- 게시글 - 댓글 (일대다)
@Entity
public class User {
@OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE)
private List<Board> boards = new ArrayList<>();
@OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE)
private List<Comment> comments = new ArrayList<>();
}
@Entity
public class Board {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@OneToMany(mappedBy = "board", cascade = CascadeType.REMOVE)
private List<Comment> comments = new ArrayList<>();
}
@Entity
public class Comment {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "board_id")
private Board board;
}
FetchType.Lazy
- N+1 방지를 위해 지연 로딩 설정
- 연관된 엔티티를 실제로 사용할 때만 조회하여 불필요한 조인 쿼리 방지
CascadeType.REMOVE : 데이터가 삭제되면 연쇄 삭제 되도록 설정
연관관계 편의 메서드
Board Entity
private void setUser(User user) {
this.user = user;
user.getBoards().add(this);
}
public void remove() {
if(this.user!=null) {
this.user.getBoards().remove(this);
}
}
setUser : 해당 게시글의 작성자가 등록되면 작성자의 게시글 목록에도 해당 게시글을 추가한다.
remove : 해당 게시글의 작성자가 존재한다면, 그 작성자의 게시글 목록에서 해당 게시글을 삭제한다.
private void setUser(User user) {
this.user = user;
user.getComments().add(this);
}
private void setBoard(Board board) {
this.board = board;
board.getComments().add(this);
}
public void remove() {
if(this.user!=null) {
this.user.getComments().remove(this);
}
if(this.board!=null) {
this.board.getComments().remove(this);
}
}
setUser : 해당 댓글의 작성자가 등록되면 작성자의 댓글 목록에 해당 댓글을 추가한다.
setBoard : 해당 댓글의 게시글이 정해지면 게시글의 댓글 목록에 해당 댓글을 추가한다.
remove : 해당 댓글의 작성자가 존재하면, 그 작성자의 댓글 목록에서 해당 댓글을 삭제하고 / 해당 댓글의 게시글이 존재하면, 그 게시글의 댓글 목록에서 해당 댓글을 삭제한다.
Set 메서드들은 private 으로 하여 엔티티 내부의 생성 메서드에서만 호출되도록 하였다.
도메인 주도 개발 (DDD)
- 객체의 일관성을 유지하고 데이터 변경 의도를 명확히 하기 위해
Setter 사용을 지양하고 생성, 변경, 수정 메서드를 만들어서 사용하였다.
- 생성 메서드들은 외부에서 호출 할 수 있도록
static 으로 하였다.
- 해당 엔티티를 생성 메서드가 아닌 기본 생성자로 외부에서 생성할 수 없도록 기본 생성자를
protected로 막아서 무분별한 객체 생성을 방지하였다.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
User Entity
public static User createUser(String name, String email, String password, LocalDateTime joinedDate, Role role) {
User user = new User();
user.name = name;
user.email = email;
user.password = password;
user.joinedDate = joinedDate;
user.role = role;
return user;
}
public void changeProfile(String name, String email) {
this.name = name;
this.email = email;
}
Board Entity
public void updateBoard(String title, String content) {
this.title = title;
this.content = content;
}
public static Board createBoard(String title, String content, User user, LocalDateTime createdAt) {
Board board = new Board();
board.title = title;
board.content = content;
board.setUser(user);
board.createdAt = createdAt;
return board;
}
public static Comment createComment(String content, User user, Board board, LocalDateTime createAt) {
Comment comment = new Comment();
comment.content = content;
comment.createAt = createAt;
comment.confirmUser(user);
comment.confirmBoard(board);
return comment;
}
public void updateComment(String content, LocalDateTime updateAt) {
this.content = content;
this.createAt = updateAt;
}