일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Java
- nginx설치
- php
- gcm 푸시 번역
- JPA
- 자바스크립트
- Design Pattern
- 페이스북 번역
- 도메인 주도 개발
- graphql
- 카프카 트랜잭션
- nginx설정
- GCM 번역
- 웹사이트 성능
- 성능
- 푸시 번역
- nginx
- 푸시
- 카프카
- kafka
- APNS
- Push
- notification
- GCM
- 웹사이트성능
- ddd
- git
- 디자인패턴
- 웹사이트최적화기법
- Today
- Total
간단한 개발관련 내용
5장 연관관계 매핑의 기초 본문
객체의 참조와 테이블의 외래 키를 매핑하는 것이 이 장의 목표다
- 방향(Direction)
- 다중성(Multiplicity)
- 연관관계 주인(Owner)
5.1 단방향 연관관계
- 회원과 팀
- 회원과 팀이 있다
- 회원은 하나의 팀에만 소속될 수 있다
- 회원과 팀은 다대일 관계다
- 객체 연관관계
- 테이블 연관관계
- 객체 연관관계와 테이블 연관관계의 가장 큰 차이
- 참조는 단방향이라 양방향을 하려면 서로 참조해야 한다. 그러나 이것은 양방향 관계가 아니라 서로 다른 단방향 관계 2개이다
- 객체 연관관계 vs 테이블 연관관계 정리
- 객체는 참조로 연관관계
- 테이블은 외래 키를 사용하여 조인으로 연관관계
5.1.1 순수한 객체 연관관계
- 객체 그래프 탐색이 가능
5.1.2 테이블 연관관계
- 테이블은 외래 키를 사용하여 조인으로 연관관계
5.1.3 객체 관계 매핑
- 회원과 팀은 @ManyToOne
5.1.4 @JoinColumn (172page) !!!!!!! 확인필요
<aside> 💡
@JoinColumn 생략
다음처럼 @JoinColumn을 생략하면 외래 키를 찾을 때 기본 전략을 사용한다.
@ManyToOne
private Team team;
- 기본 전략 : 필드명 +_+참조하는 테이블의 컬럼명
- 필드명(team) +_+참조하는 테이블의 컬럼명 </aside>
5.1.5 @ManyToOne
- optional
- false로 설정하면 연관된 엔터티가 항상 있어야 한다
- fetch
- FetchType.EAGER, FetchType.LAZY
- cascade
- 영속성전이
- targetEntity
- 엔터티 타입 정보
5.2 연관관계 사용
5.2.1 저장
- JPA에서 엔터티를 저장할 때 연관된 모든 엔터티는 영속 상태여야 한다.
5.2.2 조회
- 객체 그래프 탐색(객체 연관관계를 사용한 조회)
- 객체 지향 쿼리 사용: JPQL
- em.createQuery(sql, Member.class);
5.2.3 수정
- 단순히 불러온 엔터티의 값만 변경해두면 트랜잭션을 커밋할 때 플러시가 일어나면서 변경 감지 기능이 작동
5.2.4 연관관계 제거
- 참조에 null
5.2.5 연관된 엔터티 삭제
- em.remove()
5.3 양방향 연관관계
- 회원에서 팀은 일대다 이기 때문에 여러 건과 연관관계를 맺을 수 있으므로 컬렉션을 사용해야 한다.
- 회원 —> 팀 (Member.team)
- 팀 —> 회원 (Team.members)
- JPA는 List를 포함해서 Collection, Set, Map 같은 다양한 컬렉션을 지원한다.
- 데이터베이스 테이블은 외래 키 하나로 양방향으로 조회할 수 있다
5.3.1 양방향 연관관계 매핑
- @ManyToOne
- @OneToMany(mappedBy = “team”)
5.3.2 일대다 컬렉션 조회
5.4 연관관계 주인
- @OneToMany는 직관적으로 이해가 될 것이다. 문제는 mappedBy 속성이다.
- 테이블은 외래 키 하나로 두 테이블의 연관관계를 관리
- 엔터티를 양방향 연관관계로 설정하면 객체의 참조는 둘인데 외래 키는 하나
- 이런 차이로 인해 JPA에서는 두 객체 연관관계 중 하나를 정해서 테이블의 외래 키를 관리해야 하는데 이것을 연관관계의 주인이라 한다
5.4.1 양방향 매핑의 규칙: 연관관계의 주인
- 양방향 연관관계 매핑 시 지켜야 할 규칙이 있는데 두 연관관계 중 하나를 연관관계의 주인으로 정해야 한다. 연관관계의 주인만이 데이터베이스 연관관계와 매핑되고 외래 키를 관리(등록, 수정, 삭제)할 수 있다. 반면에 주인이 아닌 쪽은 읽기만 할 수 있다.
- 연관관계 주인을 정한다는 것은 사실 외래 키 관리자를 선택하는 것이다
5.4.2 연관관계의 주인은 외래 키가 있는 곳
- 연관관계의 주인만 데이터베이스 연관관계와 매핑되고 외래 키를 관리할 수 있다. 주인이 아닌 반대편(inverse, non-owning side)은 읽기만 가능하고 외래 키를 변경하지는 못한다.
<aside> 💡
데이터베이스 테이블의 다대일, 일대다 관계에서는 항상 다 쪽이 외래 키를 가진다. 다 쪽인 @ManyToOne은 항상 연관관계의 주인이 되므로 mappedBy를 설정할 수 없다. 따라서 @ManyToOne에는 mappedBy 속성이 없다.
</aside>
5.5 양방향 연관관계 저장
- 양방향 연관관계는 연관관계의 주인이 외래 키를 관리한다. 따라서 주인이 아닌 방향은 값을 설정하지 않아도 데이터베이스에 외래 키 값이 정상 입력된다
- 팀을 통해 멤버가 추가되는 것은 데이터베이스에 저장할 때 무시된다
- team.getMembers().add(member); // 무시(연관관계의 주인이 아님)
5.6 양방향 연관관계의 주의점
- 다시 한 번 강조하지만 연관관계의 주인만이 외래 키의 값을 변경할 수 있다
5.6.1 순수한 객체까지 고려한 양방향 연관관계
- 객체 관점에서 양쪽 방향 모두 값을 입력해주는 것이 가장 안전하다
- 결론: 객체의 양방향 연관관계는 양쪽 모두 관계를 맺어주자?? 음??
- 한 트랜잭션 안에서 연관관계의 주인에만 설정을 하고 반대편 객체에서 조회를 할 경우 조회되지 않는데 그런 것 때문에 양방향 연관관계 셋팅을 한다
- 테스트케이스에서 연관관계 문제가 나올 수도 있고~
5.6.2 연관관계 편의 메서드
- changeTeam(Team team) { … }
- 한 번에 양방향 관계를 설정하는 메서드를 연관관계 편의 메서드라고 한다
5.6.3 연관관계 편의 메서드 작성 시 주의 사항
- member의 팀을 변경할 경우, 기존 팀과 회원의 연관관계를 삭제하는 코드를 추가해야한다
<aside> 💡
…(중략)
문제는 관계를 변경하고 영속성 컨텍스트가 아직 살아있는 상태에서 teamA의 getMembers()를 호출하면 member1이 반환된다는 점이다. 따라서 변경된 연관관계는 앞서 설명한 것처럼 관계를 제거하는 것이 안전하다.
</aside>
5.7 정리
- 양방향의 장점은 반대방향으로 객체 그래프 탐색 기능이 추가된 것뿐이다.
- 주인의 반대편은 mappedBy로 주인을 지정해야 한다. 그리고 주인의 반대편은 단순히 보여주는 일(객체 그래프 탐색)만 할 수 있다.
내용을 정리하면 다음과 같다
- 단방향 매핑만으로 테이블과 객체의 연관관계 매핑은 완료되었다
- 단방향을 양방향으로 만들면 반대방향으로 객체 그래프 탐색 기능이 추가된다
- 양방향 연관관계를 매핑하려면 객체에서 양쪽 방향 모두 관리해야 한다
<aside> 💡
연관관계의 주인을 정하는 기준
단방향은 항상 외래 키가 있는 곳을 기준으로 매핑하면 된다. …(중략) 비즈니스 중요도를 배제하고 단순히 외래 키 관리자 정도의 의미만 부여해야 한다.
</aside>
양방향 매핑 시 무한루프를 조심하자
- toString(), lombok, JSON 생성 라이브러리
<aside> 💡
양방향 매핑 시에는 무한 루프에 빠지지 않게 조심해야 한다. 예를 들어 Member.toString()에서 getTeam()을 호출하고 Team.toString()에서 getMember를 호출하면 무한 루프에 빠질 수 있다. 이런 문제는 엔터티를 JSON으로 변환할 때 자주 발생하는데 JSON 라이브러리들은 보통 무한루프에 빠지지 않도록 하는 어노테이션이나 기능을제공한다.
</aside>
양방향 매핑 정리
- 단방향 매핑만으로도 이미 연관관계 매핑은 완료
- 양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐
- 데이터 조회를 위해 양방향을 하는 것
- JPQL에서 역방향으로 탐색할 일이 많음
- 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 됨
실전 예제 | 2. 연관관계 매핑 시작
페이지 요약
연관관계 매핑의 기본 개념
- 객체의 참조와 테이블의 외래 키를 매핑하는 것이 이 장의 목표이다
- 객체는 참조로, 테이블은 외래 키를 사용하여 조인으로 연관관계를 맺는다
단방향과 양방향 연관관계
- 단방향 연관관계에서는 @ManyToOne과 @JoinColumn을 사용하여 매핑한다
- 양방향 연관관계에서는 연관관계의 주인을 정해야 하며, 주인만이 외래 키를 관리할 수 있다
- 연관관계의 주인은 외래 키가 있는 쪽(다쪽)이 되어야 한다
연관관계 사용 시 주의사항
- 객체의 양방향 연관관계는 양쪽 모두 관계를 맺어주는 것이 안전하다
- 연관관계 편의 메서드를 사용하여 양방향 관계를 한 번에 설정할 수 있다
- 양방향 매핑 시 무한 루프에 빠지지 않도록 주의해야 한다