JPA

[JPA] 여러가지 연관관계 매핑

행복하개! 2020. 10. 16. 20:20

 

 

 

연관관계를 매핑할 때는 1. 다중성과 2. 단방향인지 양방향인지, 양방향일때 3. 연관관계의 주인은 누구로 설정할지가 중요하다.

 

1. 다중성

여기서 다중성은 4가지가 존재한다. 

1) 다대일 N:1 @ManyToOne 

2) 일대다 1:N @ OneToMany

3) 일대일 1:1 @OneToOne

4) 다대다 N:M @ManyToMany

 

2. 단방향, 양방향

앞서 많이 이야기 했지만 테이블은 외래 키 하나만 정해져있어도 어느 방향으로든 데이터를 불러올 수 있다(조인) 방향이라는 개념 자체가 없다. 근데 객체는 아니다. 참조하는 필드가 있는 쪽으로만 방향이 정해져있고 한쪽만 참조하면 단방향, 양쪽이 서로 참조하면 양방향이다. 근데 사실 양방향이라는 용어는 억지로 만들어낸 것이고 단방향 두개라고 생각하면 된다.

 

3. 연관관계의 주인

여기서 양방향은 참조가 2개로 단방향 2개로 이루어진다. 즉, 둘 중에서 외래키를 관리할 곳을 정해줘야 한다. 연관관계의 주인이라는 것은 여기서 외래 키를 관리하는 참조를 의미한다. 이렇게 되면 주인의 반대편 가짜매핑에는 외래 키에 영향을 주지 않고 mappedBy로 readOnly만 가능하게 된다.

 

 

 

1) 다대일 N:1 @ManyToOne 

가장 많이 사용되는 매핑이면 반대는 일대다 이다. 외래 키가 있는 곳이 연관관계의 주인으로 정해준다.

 

2) 일대다 1:N @ OneToMany

일대다 단방향은 일대다에서 일(1)이 연관관계의 주인이다. 테이블 일대다 관계는 다 쪽에 외래키가 존재하는데, 이렇게 되면 가짜매핑쪽에 외래키를 관리하게 되는 요상한 구조가 된다. 또한 @JoinColumn을 사용하지 않으면 기본적으로 @JoinTable이 되기 때문에 테이블이 자동적으로 하나가 추가되게 된다.

 

단점 : 엔티티가 관리하는 외래 키가 다른 테이블에 있게 된다. 사실 이게 너무 치명적인 단점이 된다. 또한 다른 테이블에 외래 키가 존재하기 때문에 쿼리가 실행이 될때 외래 키가 존재하는 테이블에 Update 쿼리가 실행된다. 기본적으로 쿼리가 한번 더 나가는 것이다. 대책으로는 일대다 단방향 매핑보다 다대일 양방향 매핑을 이용하는 것이 좋다.

 

일대다 양방향 매핑 또한 마찬가지이다. 이 경우에는 주인이 아닌쪽 즉 @ManyToOne쪽에 읽기전용 매핑(@JoinColumn(insertable=false, updatable=false))를 이용해서 mappedBy 처럼 사용할 수는 있다. 하지만 애초에 스펙상 주어진 공식적인 방법은 아니다. 즉, 안쓰는게 좋겠지만 가끔 실무에서는 이렇게 읽기전용처럼 만들고 사용해야하는 경우가 생길 수 있으니 알아두자.

 

그냥 다대일 양방향을 써서 이용하자.

 

3) 일대일 1:1 @OneToOne

일대일 관계는 그 반대도 일대일이다. 주 테이블이나 대상 테이블에 외래 키를 선택, 즉, 주인으로 설정할 수 있다. 다만 외래 키 데이터베이스에 UNI 제약조건을 추가하는 것이다. 일대일에는 대상 테이블에 외래 키 단방향을 만드는 방법은 JPA 스펙상 지원하지 않는다. 원한다면 양방향 매핑을 걸고 사용하면 된다.

 

주 테이블에 외래키가 있을 때 장점으로는 객체지향적이고 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인이 가능하나, 단점으로는 값이 없으면 외래 키에 null 값을 허용해야한다.

 

대상 테이블에 외래키가 있을 때 장점으로는 전통적인 데이터베이스 개발자가 선호하는 방식(DBA)이고 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조를 유지할 수 있다. 단점으로는 프록시 기능의 한계, 지연로딩으로 설정해도 즉시 로딩이 된다는 점이다.

 

4) 다대다 N:M @ManyToMany

@ManyToMany를 이용하고, @JoinTable로 연결 테이블을 지정한다.

 

※주의 : 편리해보이지만 실무에서는 절대 사용할 수가 없다. 왜냐하면 다대다 매핑은 단순하게 연결만 해주는 역할인데, 실무에서 그런 일은 발생하지 않는다. 뭐든 작은 뭐라도 컬럼으로 추가 되는게 정상적이다. 

 

이 한계를 극복하기 위해서는 테이블을 하나 더 만들고 연결 테이블로 이용하는 방법이 있다. @ManyToMany가 아닌 @OneToMany와 @ManyToOne을 이용하고 하나의 테이블에서 키를 받아서 사용한다.

'JPA' 카테고리의 다른 글

[JPA] @MappedSuperclass  (0) 2020.10.20
[JPA] 상속관계 매핑  (0) 2020.10.20
[JPA] 연관관계 매핑 기초  (0) 2020.10.12
[JPA] 데이터베이스 스키마 자동 생성  (0) 2020.10.11
[JPA] 엔티티 매핑 어노테이션  (0) 2020.10.10