📌 다중성 종류
JPA에서는 어떤 엔티티를 중심으로 상대 엔티티를 바라보느냐에 따라 다중성이 다르다.
예를 들어 게시글 하나는 여러개의 댓글을 가질 수 있으니 게시글 입장에서 댓글과는 일대다(게시글:댓글=1:N)이고, 댓글 입장에서는 게시글과 다대일(댓글:게시글=N:1) 관계다.
💡 나의개수To너의개수
📌 방향 종류
그리고 "데이터 모델링에서는 관계를 맺어주기만 하면 자동으로 양방향 관계가 되어서 서로 참조하지만, 객체지향 모델링에서는 구현하고자 하는 서비스에 따라 단방향 관계인지, 양방향 관계인지 적절한 선택을 해야 한다"고 한다.
즉 스프링 JPA에서는 연관관계 매핑을 할 때 다대일인지, 일대다인지 / 단방향인지 양방향인지까지 결정해주어야 한다는거다. (넘나 귀찮은 것)
public class Comment {
@ManyToOne
@JoinColumn(name = "post_id")
private Post post;
}
public class Post {}
이런식으로 한쪽 엔티티에만 연관관계 매핑을 하면 단방향 관계가 된다. 이렇게 쓰면 comment에서는 post를 가져올 수 있게 된다. 그렇다면 post에서 comment를 가져오고 싶으면 어떻게 할까?
public class Comment {
@ManyToOne
@JoinColumn(name = "post_id")
private Post post;
}
public class Post {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "post")
private List<Comment> comments;
}
이렇게 post에도 comment를 일대다 관계로 매핑해서 양방향 관계로 만들어주면 post에서도 comment를 리스트로 가져올 수 있게 된다.
연관관계를 매핑할때 사용하는 어노테이션들의 기능을 정리해보면 다음과 같다.
다대일(N:1) 관계 매핑
fetch
: 연관관계의 데이터를 어떻게 가져올 것인지를 지정한다.Eager Loading
(즉시 로딩) : 특정 엔티티를 조회할 때 연관된 모든 엔티티를 같이 로딩Lazy Loading
(지연 로딩) : 가능한 객체의 초기화를 지연시키는데 사용. 즉시 로딩과 달리 불필요한 조인을 줄여서 주로 권장되는 방법임💡
@ManyToOne
,@OneToOne
과 같이@XXXToOne
어노테이션들은 기본이 즉시 로딩(EAGER) 이므로, 꼭 LAZY로 명시적으로 설정해서 사용하자.
ex)@ManyToOne(fetch = FetchType.LAZY)
optional
: false
설정 시 연관된 엔티티가 null
일 수 없다.@Column(nullable=false)
같은 느낌외래키(FK) 매핑
name
: 매핑할 외래키 이름을 지정@JoinColumn(name = "post_id")
라고 작성일대다(1:N) 관계 매핑
mappedBy
: 연관관계의 주인을 정한다.mappedBy = "post"
cascade
: 특정 엔티티에 작업을 수행하면 이와 관련된 엔티티에도 동일한 작업을 수행한다. CascadeType에는 PERSIST
, MERGE
, DETACH
, PREFRESH
, REMOVE
, ALL
이 있다.cascade = CascadeType.ALL
orphanRemoval
: 이 옵션이 true
일 때 고아객체를 삭제한다.orphanRemoval = true
💡
@OneToMany
와@ManyToMany
는 기본이 지연 로딩(LAZY)이다.