이전에 Entity의 단방향/양방향 연관관계에 대해 알아봤었는데 이번에는 실제로 연관관계를 어떻게 맺는지를 알아보자.
아래의 예시들은 단방향 매핑을 기준으로 작성되었다.
// Post.java
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@Column(name = "CONTENT")
private String content;
@OneToOne
@JoinColumn(name = "USER_ID", insertable = false, updatable = false)
private User createdBy;
}
// User.java
@Entity
public class User {
@Id @GeneratedValue
@Column(name = "USER_ID")
private Long id;
@Column(name = "NAME")
private String name;
}
// Post.java
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@Column(name = "CONTENT")
private String content;
@OneToOne
@JoinColumn(name = "USER_ID", insertable = false, updatable = false)
private User createdBy;
}
// User.java
@Entity
public class User {
@Id @GeneratedValue
@Column(name = "USER_ID")
private Long id;
@Column(name = "NAME")
private String name;
@OneToOne(mappedBy = "createdBy")
private Post post;
}
모든 게시글(Post)은 작성자(User)를 하나 반드시 가진다. 다만 실제로는 작성자는 여러 게시글을 작성할 수 있는 일대다 관계지만 하나만 작성할 수 있다고 가정하고 작성했다.
// Board.java
@Entity
public class Board {
@Id @GeneratedValue
@Column(name = "BOARD_ID")
private Long id;
@Column(name = "NAME")
private String name;
@OneToMany
@JoinColumn(name = "POST_ID", insertable = false, updatable = false)
private List<Post> posts = new ArrayList<>();
}
// Post.java
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@Column(name = "CONTENT")
private String content;
}
지난 포스팅에서 단방향 매핑의 예시로 사용했던 코드이다. 게시글 Entity가 가지고있는 boardId 속성을 기준으로 게시판(1)이 게시글(N) 목록을 속성으로 가지고 있는 형태로써 상대방 속성을 가지고있는 게시판을 기준으로 1:N 매핑이 된다.
// Board.java
@Entity
public class Board {
@Id @GeneratedValue
@Column(name = "BOARD_ID")
private Long id;
@Column(name = "NAME")
private String name;
}
// Post.java
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@Column(name = "CONTENT")
private String content;
@Column(name = "BOARD_ID")
private String boardId;
@ManyToOne
@JoinColumn(name = "BOARD_ID", insertable = false, updatable = false)
private Board board;
}
// Board.java
@Entity
public class Board {
@Id @GeneratedValue
@Column(name = "BOARD_ID")
private Long id;
@Column(name = "NAME")
private String name;
@OneToMany(mappedBy = "board", fetch = FetchType.EAGER)
private List<Post> posts = new ArrayList<>();
}
// Post.java
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@Column(name = "CONTENT")
private String content;
@Column(name = "BOARD_ID")
private String boardId;
@ManyToOne
@JoinColumn(name = "BOARD_ID", insertable = false, updatable = false)
private Board board;
}
N:1 매핑은 1:N 매핑과 유사하지만 연관관계의 주인이 1측(게시글측)이 된다는 점에서 다르다.
// Board.java
@Entity
public class Board {
@Id @GeneratedValue
@Column(name = "BOARD_ID")
private Long id;
@Column(name = "NAME")
private String name;
}
// Post.java
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@Column(name = "CONTENT")
private String content;
@Column(name = "BOARD_ID")
private String boardId;
@ManyToOne
@JoinColumn(name = "BOARD_ID", insertable = false, updatable = false)
private Board board;
}
// Board.java
@Entity
public class Board {
@Id @GeneratedValue
@Column(name = "BOARD_ID")
private Long id;
@Column(name = "NAME")
private String name;
@ManyToMany(mappedBy = "boards", fetch = FetchType.EAGER)
private List<Post> posts = new ArrayList<>();
}
// Post.java
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@Column(name = "CONTENT")
private String content;
@Column(name = "BOARD_ID")
private String boardId;
@ManyToMany
@JoinTable(name = "BOARD_POST")
private List<Board> boards = new ArrayList<>();
}
실제로 이런 경우는 없지만 한 게시글이 여러 게시판에 속할 수 있고 한 게시판이 여러 게시글을 가진 다대다 관계라고 가정하고 작성하였다.
다만 이와 같이 @ManyToMany 어노테이션을 사용한 다대다 매핑은 소스상에서 컨트롤할 수 없는
JoinTable을 생성하여 매핑하는 방식이다.해당 테이블에
PK가 아닌 다양한 데이터가 들어갈 수 있고 제어가 불가능하며, 예상치 못한 복잡한 Join 쿼리가 발생하여 성능이 저하될 수 있다.그러므로 다대다 매핑이 필요한 경우 직접
JoinTable을Entity로 작성하여 다대일 - 일대다 로 매핑하는 것이 좋다.