Entity의 연관관계란 쉽게 말해 클래스안에 다른 Entity를 속성으로 가지고 있냐는 것이다. 예를 들어, 게시판 기능을 만든다고 가정하면 게시판이 있을 것이고, 게시글이 있을 것이다. 뿐만 아니라 해당 글을 작성한 사용자도 있을 것이다.
이 때, 특정 게시판으로 들어가면 해당 게시판의 게시글을 모두 조회할 수 있어야 하는데, 그러기 위해서는 게시판에 게시글 Entity의 Collections가 속성으로 들어가 있어야만 할 것이다.
여기서 기능이 더 확장된다면 댓글 기능, 대댓글 기능, 게시글 추천 기능 등 다양한 기능이 추가될수록 이 연관관계는 복잡해질 것이다.
이 때 Entity간의 연관관계를 매핑하는 방식에는 양방향 매핑과 단방향 매핑이 있는데, 쉽게 말해 한쪽만 다른 쪽을 속성으로 갖는지, 아니면 서로 서로를 속성으로 가질 지의 차이다.
// 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;
}
위와 같이 게시판만 게시글 속성을 가지고 있고 게시글은 게시판을 속성으로 가지지 않는 것이 단방향 관계이다.
이런 경우 보통 게시글 객체에 게시판의 PK를 넣어 두고 해당 값을 이용하여 연관관계를 정의한다. 참고로 이와 같은 경우를 게시글이 연관관계의 주인이 된다고 한다. (상대방의 PK를 가지고 있는 쪽이 연관관계를 정의하므로 주인이 된다)
// 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;
}
이렇게 게시판과 게시글이 서로 서로를 속성으로 가지고 있는 경우를 양방향 매핑이라고 한다. 이 경우에는 게시글은 게시판의 PK를 가지고 있기 때문에 해당 값으로 게시판 객체를 조회할 수 있다. 즉, 양방향 매핑이라고 해도 연관관계의 주인을 정하는 것은 필수적인 작업으로 양쪽이 다 서로의 PK를 가지고 있어선 안된다. (유사한 경우 매핑 테이블을 가운데 따로 두기도 한다.)
이렇게 말로만 들으면 당연히 양방향 매핑을 사용하는게 더 좋고 효율적이라고 느낄 수 있다.
하지만 위의 예시에서는 빠져있지만 사용자 Entity가 있다고 가정해보자. 사용자는 게시판 및 게시글의 생성자/수정자 속성으로도 들어갈 것이다. 또한 댓글, 대댓글, 추천 등 기능이 많아지면 많아질수록 사용자가 맺는 연관관계는 매우 많아질 것이다.
이렇게 되면 게시글 하나 불러오려다가 게시글과 연관된 게시판, 작성자 또 그와 연관된 객체들 등 매우 비효율적인 구조가 된다.
그러므로 연관관계는 왠만하면 기본적으로 단방향으로 설정하고, 꼭 필요할때만 양방향 매핑을 설정하는 것이 좋다.
[JPA] Entity 연관관계 매핑하기 - 1:1(@OneToOne), 1:N(@OneToMany), N:1(@ManyToOne), N:M(@ManyToMany)