Develop/Spring

[Spring/JPA] 연관관계 매핑

순무엄마동생 2020. 12. 20. 01:25

*인프런 김영한 강사님 JPA 로드맵 강좌를 기반으로 정리한 내용입니다!

 

연관관계 매핑

관계형 DB 테이블에서는 FK를 통해 양방향으로 조회를 할 수 있습니다.

 

교수, 수업 이 두가지 테이블를 예시로 사용하겠습니다.

- 교수님은 여러 수업의 강의를 맡을 수 있습니다.

- 한 수업에는 한 교수님이 강의를 맡으십니다.

 

[Table]

노란색은 PK / 분홍색은 FK

현재 수업을 담당하는 교수님을 알고 싶다면

select * from CLASSES c 
	join PROFESSOR p on c.professor_id = p.professor_id;

 

교수님이 담당하는 모든 수업을 알고 싶다면

select * from PROFESSOR p 
	join CLASSES c on p.professor_id = c.professor_id;

 

이렇게 FK를 이용하여 양방향 테이블을 모두 조회할 수 있습니다.

 

[Entity]

JPA에서도 매핑을 통해 연관된 테이블 객체를 가져올 수 있습니다.

@Entity
public class Professor {

    @Id @GeneratedValue
    @Column(name = "professor_id")
    private Long id;
    private String professor_name;
    private String phone;

    @OneToMany(mappedBy = "professor")
    private List<Classes> classes = new ArrayList<>();
}
@Entity
public class Classes {

    @Id @GeneratedValue
    @Column(name = "class_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "professor_id")
    private Professor professor;
    
    private String className;
}

위와 같이 @OneToMany와 @ManyToOne 이라는 어노테이션을 사용해서 연결할 수 있습니다.

sql은 FK 하나만 사용해서 양쪽 테이블을 참조할 수 있지만 객체는 양쪽에서 각자의 엔티티로 매핑을 해줘야 합니다. 이를 양방향 매핑이라 부르며 단방향 매핑을 2개 사용한 것입니다. 이제 매핑 방법에 대해서 설명하겠습니다!

 

 

연관관계 매핑방법

관계형 DB에서의 관계는 1:1 / 1:N / N:M 이렇게 3가지가 있습니다.

 

- 1:1인 경우, 양쪽에 @OneToOne 어노테이션을 사용하면 됩니다.

- 1:N인 경우, 1인 곳에 @OneToMany를 N인 곳에 @ManyToOne을 사용하면 됩니다.

- N:M인 경우, 양쪽에 @ManyTo@Many를 사용해줍니다.

 

위의 방법은 양방향 매핑법을 설명한 것인데 꼭 모든 곳에 양방향 매핑을 할 필요는 없습니다.

필요한 곳에 알맞은 방법으로 단방향/양방향 중 선택해서 사용하면 됩니다.

 

※ 하지만 N:M은 실제로 특수한 경우를 제외하고 사용하지 않는다고 알고 있습니다! 보통 중간 테이블을 하나 만들어서 1:N과 N:1의 관계로 푸는 것으로 알고 있습니다!

 

 

 

연관관계 매핑의 Owner

@Entity
public class Professor {

    @Id @GeneratedValue
    @Column(name = "professor_id")
    private Long id;
    private String professor_name;
    private String phone;

    @OneToMany(mappedBy = "professor")
    private List<Classes> classes = new ArrayList<>();
}

mappedBy라는 것을 볼 수 있습니다.

말 그대로 'professor에 의해 매핑되었다!'라는 의미이며 Classes 객체 안에 있는 professor를 의미합니다.

 

왜 필요하지?

db에서는 FK를 하나만 가지고 양쪽을 조회할 수 있습니다.

JPA는 1개인 FK를 양쪽에 세팅해줬기 때문에 한 곳에서 FK 관리할 곳을 정해줘야합니다.

mappedBy가 적힌 곳(Professor)은 단순 조회만 하는 용도이며, 반대편(Classes)이 실제 FK를 관리하는 곳입니다.

 

- 연관관계의 주인만이 FK를 관리합니다. (등록/수정)

- 주인이 아닌 쪽은 읽기만 가능합니다.

 

주인은 어떻게 정하지?

일반적으로 FK가 존재하는 곳을 주인으로 합니다.