1. @ManyToOne vs @OneToMay
1.1. @ManyToOne?
@ManyToOne은 다대일(Many-to-One) 관계를 의미합니다. 이 어노테이션은 FK를 속성으로 가지는 테이블에 사용합니다.
- @ManyToOne 사용 예시
@Entity
public class Plan {
@ManyToOne(fetch = FetchType.LAZY) // Plan의 속성에 user_id가 포함됨.
@JoinColumn(name = "user_id") // FK
private User user;
}
1.2. @OneToMany?
@OneToMany는 일대다(One-to-Many) 관계를 의미합니다. 이 어노테이션은 매핑이 되는 객체를 의미합니다.
@Entity
public class User {
@OneToMany(mappedBy = "user") // Plan.user 필드에 의해 매핑됨. user는 여러개의 plan을 가질 수 있다.
private List<Plan> plans = new ArrayList<>();
}
<br>
2. 기억하는 방법
일대다, 다대일 관계는 대부분 한 문장에서 파생됩니다.
user는 여러 개의 plan을 가질 수 있다.
관리자는 여러 개의 게시물을 가질 수 있다.
카테고리는 여러 개의 게시물을 가질 수 있다.
위 문장에서 앞에 위치한 엔티티는 하나(One)만 존재하므로 @OneToMany을 사용하여 뒤의 엔티티를 매핑해주어야합니다.
그리고 뒤에 위치한 엔티티는 여러 개(Many)가 존재할 수 있으므로 @ManyToOne을 사용하여 앞의 엔티티를 매핑해주어야합니다.
<br>
3. 다대다 관계
게시물은 여러 개의 태그를 가질 수 있다.
태그는 여러 개의 게시물을 가질 수 있다.
두 개의 엔티티는 서로가 서로를 여러개 가질 수 있는 관계입니다. 이를 다대다 관계라고하며, 다대다 관계는 중간 테이블을 엔티티로 승격해서 일대다, 다대일로 쪼개야합니다.
쪼개지 않고 다대다 관계로 엔티티를 구성할 경우 ~~~과 같은 문제가 발생하기 때문입니다.
3.1 다대다 관계 분리하는 방법
게시물은 여러 개의 태그를 가질 수 있다.
태그는 여러 개의 게시물을 가질 수 있다.
게시물과 태그는 서로를 여러 개 참조할 수 있는 다대다 관계입니다. 이를 해결하기 위해 중간 엔티티인 게시물-태그 엔티티를 생성하여 위 문장을 다시 작성하겠습니다.
게시물은 여러 개의 게시물-태그를 가질 수 있다.
태그는 여러 개의 게시물-태그를 가질 수 있다.
나누게 되면 서로가 서로를 참조하지 않게 되었습니다. 이제 어디에 어떤 어노테이션을 달아야하는지 보입니다.
| enitity | annotation | mapping entity |
|---|---|---|
| 게시물 | @OneToMany | 게시물-태그 |
| 태그 | @OneToMany | 게시물-태그 |
| 게시물-태그 | @ManyToOne | 게시물, 태그 |
아래는 구현된 코드입니다. 실제 이 블로그를 구현하기 위해 사용한 엔티티입니다.
@Entity
@Getter
@Table(name = "post_tag")
public class PostTag extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "post_id", nullable = false)
private Post post;
@ManyToOne
@JoinColumn(name = "tag_id", nullable = false)
private Tag tag;
public PostTag(Post post, Tag tag) {
this.post = post;
this.tag = tag;
}
}