외래키와 연관관계
- 외래 키를 관리하는 테이블, 객체(엔티티)가 연관관계의 주인입니다.
- 주인이 아니면 mappedBy 속성을 사용해 주인 필드 이름을 값으로 입력합니다.
다대일(@ManyToOne)
[Member <-> Team]
- 연관관계의 주인은 항상 다(N)쪽입니다.
- ERD에서 화살표 실선은 연관관계 주인이며 점선은 주인이 아니라는 표시입니다.
- 주인이 아닌 객체는 조회를 위한 JPQL이나 객체 그래프를 탐색할 때 사용합니다.
- 양방향 연관관계는 항상 서로를 참조해야 합니다.
- 서로를 참조하기 위해선 편의상 메소드를 작성하는 것이 좋습니다.
- Member의 setTeam()과 Team의 addMember() 메소드가 그런 메소드들입니다.
- 메소드는 한쪽에만 작성하는 것이 좋으며 양쪽에 다 작성하면 무한루프에 빠질 수 있습니다.
- 양쪽에 작성할 경우 하나만 호출하면 됩니다. 또한 무한루프에 빠지지 않도록 검사하는 로직도 있습니다.
일대다 단방향의 단점(@OneToMany)
- 관리하는 외래 키가 다른 테이블에 있다는 점
- e.g. team.getMembers().getTeamId로 외래 키를 관리하는 비효율이 발생합니다.
- 소스코드 : TeamTest
- 소스코드 : TeamTest
- e.g. team.getMembers().getTeamId로 외래 키를 관리하는 비효율이 발생합니다.
- 따라서 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용
- 다른 테이블의 외래 키를 관리해야하는 점은 성능 문제도 있지만 관리도 부담됩니다.
- 다대일 양방향은 외래 키가 본인 테이블에 있기 때문에 이런 문제가 발생하지 않습니다.
일대다 양방향
- 일대다 양방향을 쓰려면 주인 엔티티(Member)에 @Joincolumn(insertable=false, updatable = false) 를 지정해 읽기 전용으로 만들어야 합니다. 하지만 일대다 단방향이 가지는 단점을 그대로 가집니다.
- 따라서 다대일 양방향을 사용해야합니다.
일대일 관계(@OneToOne)
[Member <-> Locker]
- 외래 키를 주 테이블, 대상 테이블 둘 중 어느 곳에서든 관리할 수 있습니다. 외래 키를 객체 참조와 비슷하게 사용할 수 있어서 주로 주 테이블에서 관리합니다.
단방향 매핑
- 일대일 관계에서 대상 테이블에 외래키가 있는 매핑은 JPA에서 지원하지 않습니다.(일대다의 경우 지원)
다대다 관계(@ManyToOne)
다대다는 실무에서 잘 사용하지 않습니다. - 저자 강의 중
- 이유 :
- 매핑의 한계 : 연결 테이블이 단순히 연결만 하지않고 추가 컬럼이나 데이터가 생겨날 수 있음
- 예상치 못한 쿼리문 : 연결 테이블 때문에 내가 예상못한 쿼리문이 나갈 리스크가 있음
- 결론 : 일대다, 다대일 양방향으로 풀어야 합니다.
- 사용자 테이블과 상품 테이블을 관계로 풀어낼 때 중간에 연결 테이블을 추가해야 합니다.
- Member - Member_Product - Product
- Member - Member_Product - Product
- 객체는 @ManyToMany를 사용해 다대다 관계를 만들 수 있습니다.ㅇ
양방향
- (주인이 아닌 엔티티에) mappedBy를 추가하고 편의 메소드를 만들어 관리합니다.
- e.g. Member <-> Product 상호 mappedBy 추가
다대다 매핑의 한계의 극복
- 연결관계 테이블에 컬럼이 추가됐을 때 @ManyToMany를 사용할 수 없습니다.
- 일대다, 다대일 관계로 풀어야 합니다.
- e.g. OrderAmount(수량)이 추가됐을 경우,
- 연결 테이블 엔티티 MemberProduct 엔티티를 생성해줘야 합니다.
- Member - MemberProduct 간 1:N(외래키를 가짐) 관계를 설정해줍니다.
- e.g. OrderAmount(수량)이 추가됐을 경우,
복합 기본 키
- MemberProduct처럼 기본 키가 둘인 경우 별도의 식별자 클래스를 만들어야 합니다.
- 엔티티에는 @IdClass를 지정해줍니다.
복합키 식별자 클래스(MemberProductId)의 특징에는
- 별도의 식별자 클래스로 만들어야 합니다.
- Serializable을 구현해야 합니다.
- equals와 hashCode 메소드를 구현해야 합니다.
- 기본 생성자가 있어야 합니다.
- 식별자 클래스는 public이어야 합니다.
- @IdClass 외에 @EmbeddedId를 사용하는 방법도 있습니다.
하지만 복합키를 사용할 땐 복잡하다는 단점이 있습니다. 대안으로 대리 키를 사용하는 것입니다.
다대다 연관관계 정리
- 다대다 관계를 일대다 다대일 관계로 풀어내기 위해 연결 테이블을 만들 때 식별자를 어떻게 구성할지 선택해야 합니다.
- 식별 관계 : 받아온 식별자를 기본 키 + 외래 키로 사용
- 비식별 관계(Order.class) : 받아온 식별자는 외래 키로만 사용하고 새로운 식별자를 추가
2번 방법이 복합키를 위한 식별자를 만들지 않아도 되므로 편리하게 ORM 매핑을 할 수 있습니다.
- 소스코드 : ProductTest
출처 : 자바 ORM 표준 JPA 프로그래밍 스터디
klyhyeon/JPAStudy
Contribute to klyhyeon/JPAStudy development by creating an account on GitHub.
github.com
'spring > jpa' 카테고리의 다른 글
자바 ORM 표준 JPA 프로그래밍 - 8장 프록시 (0) | 2021.07.08 |
---|---|
자바 ORM 표준 JPA 프로그래밍 - 7장 고급매핑 (0) | 2021.07.08 |
자바 ORM 표준 JPA 프로그래밍 - 5장 연관관계 매핑 기초 (0) | 2021.07.05 |
자바 ORM 표준 JPA 프로그래밍 - 3장 JPA 영속성 컨텍스트 (0) | 2021.07.05 |
자바 ORM 표준 JPA 프로그래밍 - 2장 JPA시작 (0) | 2021.07.05 |
댓글