Chapter 5: 연관관계 매핑 기초
1. 단방향 연관 관계
객체 연관관계와 테이블 연관관계의 가장 큰 차이
참조
를 통한 연관관계는 언제나단방향
이다객체간에
양방향
으로 만들고 싶으면 반대쪽에도 필드를 추가해서 참조를 보관해야한다결국 연관관계를 하나 더 만들어야 한다
이렇게 양쪽에서
서로 참조
하는 것을양방향 연관관계
라 한다하지만 정확히 이야기하면, 이것은 양방향 관계가 아니라 서로 다른
단방향 관계 2개
다반면, 테이블은
외래 키
하나로 양방향으로 조인할 수 있다
객체 연관관계 vs 테이블 연관관계
객체
참조 (주소)
로 연관관계를 맺는다연관된 데이터를
참조
를 사용해 조회한다연관관계를 참조를 사용해서 탐색하는 것을
객체 그래프 탐색
이라 한다
참조를 사용하는 객체의 연관관계는
단방향
이다객체를 양방향으로 참조하려면, 단방향 연관관계를 2개 만들어야 한다
테이블
외래 키
로 연관관계를 맺는다연관된 데이터를
JOIN
을 통해 조회한다외래 키를 사용해서 연관관계를 탐색하는 것을
JOIN
이라 한다
외래 키를 사용하는 테이블의 연관관계는
양방향
이다
@JoinColumn
@JoinColumn
외래 키를 매핑할 때 사용한다
속성
속성기능기본값name
매핑할 외래 키 이름을 지정한다
필드명 + _ + 참조하는 테이블의 기본 키 컬럼명
referencedColumnName
외래 키가 참조하는 대상 테이블의 컬럼명
차모하는 테이블의 기본 키 컬럼명
foreignKey (DDL)
외래 키 제약조건을 직접 지정할 수 있다 (이 속성은 테이블을 생성할 때만 사용!)
unique , nullable , insertable , updatable, columnDefinition, table
@Column 의 속성과 같다
@JoinColumn
생략해당 어노테이션을 생략하면 외래 키를 찾을 때
기본 전략
을 사용한다기본 전략
필드명 + _ + 참조하는 테이블의 컬럼명
@ManyToOne
@ManyToOne
이름 그대로 다대일 (N:1) 관계라는 매핑 정보다
연관관계를 매핑할 때 이렇게 다중성을 나타내는 어노테이션을 필수로 사용해야 한다
속성
속성기능기본값optional
false로 설정하면 연관된 엔티티가 항상 있어야 한다
true
fetch
global fetch 전략을 설정
FetchType.EAGER
cascade
영속성 전이 기능을 사용
targetEntity
연관된 엔티티의 타입 정보를 설정한다 (이 기능은 거의 사용하지 않는다! 컬렉션을 사용해도 제네릭으로 타입 정보를 알 수 있기 때문!)
2. 연관관계 사용
2-1. 저장
JPA에서 엔티티를 저장할 때 연관된 모든 엔티티는
영속 상태
여야 한다JPA는 참조한 객체의
식별자
를외래 키
로 사용해서 적절한등록 쿼리
를 생성한다
2-2. 조회
연관관계가 있는 엔티티를 조회하는 방법
객체 그래프 탐색
객체 연관관계를 사용한 조회
객체지향 쿼리 사용 (JPQL)
예를 들어 회원을 대상으로 조회하는데 팀1에 소속된 회원만 조회하려면, 회원과 연관된 팀 엔티티를 검색 조건으로 사용해야 한다
SQL은 연관된 테이블을 JOIN 해서 검색조건을 사용하면 된다
JPQL도
JOIN
을 지원한다 (문법은 약간 다름!)
JPQL은 객체(엔티티)를 대상으로 하고, SQL보다 간결하다
2-3. 수정
수정은 em.update() 같은 method가 없다
단순히 불러온
엔티티의 값만 변경
해두면, 트랜잭션을커밋
할 때플러시
가 일어나면서변경 감지
기능이 작동한다그리고 변경사항을 데이터베이스에 자동으로 반영한다
연관관계를 수정할 때도 같은데,
참조하는 대상
만 변경하면 나머지는 JPA가 자동으로 처리한다
2-4. 연관관계 제거
: 연관관계를 null
로 설정
2-5. 연관된 엔티티 삭제
연관된 엔티티를 삭제하려면 기존에 있던
연관관계를 먼저 제거
하고삭제
해야 한다그렇지 않으면 외래 키 제약조건으로 인해, DB에서 오류가 발생한다
3. 양방향 연관관계
데이터베이스 테이블은 외래 키 하나로 양방향으로 조회할 수 있다
객체는 연관관계가 맺어진 반대 방향에서도 접근할 수 있게,
컬렉션
과@OneToMany
매핑 정보, 그리고mappedBy
속성을 사용한다ex)
회원 → 팀 (Member.team)
팀 → 회원 (Team.members)
여기서 members는 list
mappedBy
속성은 양방향 매핑일 때 사용하는데, 반대쪽 매핑의 필드 이름을 값으로 주면 된다
4. 연관관계의 주인
mappedBy
가 필요한 이유테이블은
외래 키
하나로 두 테이블의 연관관계를 관리엔티티를 단방향으로 매핑하면 참조를 하나만 사용하므로 이 참조로 외래키를 관리하면 됨
but, 엔티티를
양방향
으로 매핑하면 양쪽에서서로를 참조
하게 됨따라서 객체의 연관관계를 관리하는 포인트는 2곳으로 늘어난다
객체의 참조는 둘인데, 외래 키는 하나다
이러한 차이로 인해 JPA에서는 두 객체 연관 관계 중 하나를 정해서 테이블의 외래 키를 관리해야 하는데, 이것을
연관관계의 주인
이라 한다
연관관계의 주인
연관관계의 주인만이 DB 연관관계와 매핑되고, 외래키를 관리할 수 있다
주인이 아닌 쪽은 읽기만 할 수 있다
주인은
mappedBy
속성을 사용하지 않는다주인이 아니면
mappedBy
속성을 사용해서속성의 값
으로연관관계의 주인
을지정
해야 한다
연관관계의 주인을 정한다는 것은
외래 키 관리자
를 선택하는 것이다연관관계의 주인은
외래 키가 있는 곳
을 뜻한다연관관계의 주인만 데이터베이스 연관관계와 매핑되고, 외래 키를 관리할 수 있다
주인이 아닌 반대편은 읽기만 가능하고, 외래키를 변경하지는 못한다
5. 양방향 연관관계 저장
양방향 연관관계는 연관관계의 주인이 외래 키를 관리한다
따라서 주인이 아닌 방향은 값을 설정하지 않아도 데이터베이스에 외래 키 값이 정상 입력된다
6. 양방향 연관관계 주의점
양방향 연관관계를 설정하고 가장 흔히 하는 실수는, 연관관계의 주인에는 값을 입력하지 않고, 주인이 아닌 곳에만 값을 입력하는 것이다
연관관계의 주인
만이외래 키
의값
을변경
할 수 있다는 것을 기억하자!
6-1. 순수한 객체까지 고려한 양방향 연관관계
연관관계의 주인에만 값을 저장하고 주인이 아닌 곳에는 값을 저장하지 않는 것이 아니라,
객체 관점
에서양쪽 방향
에 모두 값을 입력해주는 것이 가장 안전하다양쪽 방향 모두 값을 입력하지 않으면 JPA를 사용하지 않는 순수한 객체 상태에서 심각한 문제가 발생할 수 있다
결론
객체의 양방향 연관관계는
양쪽 모두 관계를 맺어주자
!
6-2. 연관관계 편의 메소드
연관관계 설정 method를 각각 호출하다 보면 실수로 둘 중 하나만 호출해서 양방향이 깨질 수 있다
양방향 관계에서 두 코드는 하나인 것처럼 사용하는 것이 안전한다
한 번에 양방향 관게를 설정하는 method를
연관관계 편의 method
라 한다
7. 정리
단방향 매핑과 비교해서 양방향 매핑은 복잡하다
연관관계의 주인도 정해야 하고, 두 개의 단방향 연관관계를 양방향으로 만들기 위해 로직도 잘 관리해야 한다
중요한 사실은 연관관계가 하나인 단방향 매핑은 언제나 연관관계의 주인이라는 점이다!
양방향은 여기에 주인이 아닌 연관관계를 하나 추가했을 뿐이다
결국 단방향과 비교해서 양방향의 장점은
반대 방향으로 객체 그래프 탐색 기능이 추가된 것
뿐이다
단방향 매핑만으로 테이블과 객체의 연관관계 매핑은 이미 완료되었다
단방향을 양방향으로 만들려면 반대방향으로
객체 그래프 탐색
기능이 추가된다양방향 연관관계를 매핑하려면 객체에서
양쪽 방향
을모두 관리
해야 한다양방향 매핑은 복잡하다
우선 단방향 매핑을 사용하고, 반대 방향으로 객체 그래프 탐색 기능(JPQL 쿼리 탐색 포함)이 필요할 때 양방향을 사용하도록 코드를 추가해도 된다
Last updated