[Spring] JPA 연관관계 매핑 (1:N)

김재연·2023년 3월 9일
0

수숙관

목록 보기
5/17
post-thumbnail

연관관계 다중성

📌 다중성 종류

  • Many To One: 다대일 (N : 1)
  • One To Many: 일대다 (1 : N)
  • One To One: 일대일 (1 : 1)
  • Many To Many: 다대다 (N : N)

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를 리스트로 가져올 수 있게 된다.

어노테이션

연관관계를 매핑할때 사용하는 어노테이션들의 기능을 정리해보면 다음과 같다.

1. @ManyToOne

다대일(N:1) 관계 매핑

  • fetch : 연관관계의 데이터를 어떻게 가져올 것인지를 지정한다.
    => Eager Loading(즉시 로딩) : 특정 엔티티를 조회할 때 연관된 모든 엔티티를 같이 로딩
    => Lazy Loading(지연 로딩) : 가능한 객체의 초기화를 지연시키는데 사용. 즉시 로딩과 달리 불필요한 조인을 줄여서 주로 권장되는 방법

💡@ManyToOne, @OneToOne과 같이 @XXXToOne 어노테이션들은 기본이 즉시 로딩(EAGER) 이므로, 꼭 LAZY로 명시적으로 설정해서 사용하자.
ex) @ManyToOne(fetch = FetchType.LAZY)

  • optional : false 설정 시 연관된 엔티티가 null일 수 없다.
    => @Column(nullable=false)같은 느낌

2. @JoinColumn

외래키(FK) 매핑

  • name : 매핑할 외래키 이름을 지정
    => ex) Comment 엔티티는 Post 엔티티의 ID 필드를 외래키로 가지므로, @JoinColumn(name = "post_id")라고 작성

3. @OneToMany

일대다(1:N) 관계 매핑

  • mappedBy : 연관관계의 주인을 정한다.
    => ex) comments 필드는 post에 의해 매핑되므로, mappedBy = "post"
  • cascade : 특정 엔티티에 작업을 수행하면 이와 관련된 엔티티에도 동일한 작업을 수행한다. CascadeType에는 PERSIST, MERGE, DETACH, PREFRESH, REMOVE, ALL이 있다.
    => ex) cascade = CascadeType.ALL
  • orphanRemoval : 이 옵션이 true일 때 고아객체를 삭제한다.
    => ex) orphanRemoval = true

💡@OneToMany@ManyToMany는 기본이 지연 로딩(LAZY)이다.


Reference

[스프링부트 JPA] 연관관계 매핑

profile
일기장같은 공부기록📝

0개의 댓글