일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 자바서블릿
- 제너릭
- JPQL
- calendar
- fullcalendar
- joinfetch
- 페이징
- jQueryUI
- 페치조인
- 스프링데이터흐름
- values()
- JQuery
- 제네릭
- namedQuery
- jscalendar
- 벌크연산
- 프로젝트생성
- jQuery값전송
- 엔티티직접사용
- JPA
- springflow
- Hibernate
- javaservlet
- paging
- javascriptcalendar
- Generic
- 대량쿼리
- fetchjoin
- LIST
- jQuery값전달
- Today
- Total
가자공부하러!
Hibernate(5) - 연관관계 매핑 본문
1. 문제점
> 객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력 관계를 만들 수 없다.
- 테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
- 객체는 참조를 사용해서 연관된 객체를 찾는다.
2. 단방향 연관관계
> 단방향 매핑으로 끝내는게 베스트
- 단방향 매핑만으로도 이미 연관관계 매핑은 완료된 것이기 때문
> 객체 지향 모델링
- Member가 필드로 Team타입의 변수를 가짐
- @ManyToOne, @JoinColumn(name = "TEAM_ID")
3. 양방향 연관관계
> FK로 엮인 DB 테이블 끼리는 JOIN을 통해 서로의 데이터를 쉽게 조회할 수 있다.
> Entity가 테이블처럼 동작하기 위해서는 별도의 작업이 필요하다.
> 객체는 가급적 단반향 연관관계를 갖게끔 설계하는 것이 좋다.
> mappedBy는 왜쓰죠?
- 객체와 테이블 간 연관관계를 맺는 차이를 이해하면 쉽다.
- 객체의 양방향 관계는 사실 서로 다른 단방향 관계 2개다.
- 둘 중 하나로 외래 키를 관리해야 하는 경우에 연관관계의 주인을 설정한다.
- 연관관계의 주인만이 외래키를 관리한다.
- 주인은 주체이기 때문에 mappedBy를 사용하지 않는다.
- 주인이 아닌쪽에는 mappedBy로 주인이 누구인지 지정해주어야 한다.
- 주인은 외래키가 있는 곳으로 정해주는 것이 좋다. (외래키를 갖는 곳)
- n:1 관계에서는 n쪽이 연관관계의 주인이다
4. 양방향 매핑시 주의점
> 연관관계의 주인에 값을 입력하지 않음
- 연관관계의 주인이 아닌곳에는 값을 입력하지 않아도 됨
- 순수한 객체 관계를 고려하면 주인과 주인이 아닌 쪽 모두에 값을 넣어주는게 맞다.
> 양방향 매핑 무한루프 조심
- ex1) toString(), lombok : 필요에 의해 직접 만들어서 쓰기(자동완성 말고)
- ex2) JSON 생성 라이브러리 : 컨트롤러에서 엔티티를 반환하면 안됨. 이것만 조심
> [tip] 연관관계 편의 메소드 활용
- 연관관계 주인에 연관관계 주인이 아닌 것을 넣을 때 연관관계 주인이 아닌 곳에 add
- ex) 주인:Member에 team, 주인아님 : Team
@Entity
@Table(name = "MEMBER")
public class Member {
.....
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
.....
public void changeTeam(Team team){
this.team = team;
team.getMembers().add(this);
}
}
5. 연관관계 매핑 케이스
> 다대일(N : 1) : 보통 가장 많이 사용됨
- 객체에는 '다'쪽에 연관관계 주인이 있고, 테이블에는 '다' 쪽에 외래키가 있어야 함
- 양방향 매핑을 하려면? : @OneToMany(mappedBy = "연관관계주인필드")
- @ManyToOne에는 mappedBy속성이 없다.
> 일대다(1 : N)
- JPA 표준스펙에서 지원하기는 하지만 권장되지 않음
- 객체에는 '일'쪽에 연관관계 주인이 있지만, 테이블에는 '다'쪽에 외래키가 있음
- 일대다 양방향 매핑은 공식적으로 없음
> 일대일(1 : 1)
- 주 테이블에 외래키를 넣거나 대상 테이블에 외래키를 넣거나 선택 가능
- 외래키에 UNIQUE 제약 조건이 있어야 문제발생 가능성이 낮음
- 외래키가 있는 곳이 연관관계의 주인이다.
> 다대다(N : M)
- RDB는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없음
- 연결(중간) 테이블을 추가해서 일대다, 다대일 관계로 풀어야함
- 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계 표현 가능
- @ManyToMany @JoinTable(name = "연결테이블이름")
- 한계
- 연결테이블에 수정이나 추가 작업이 불가능
- 연결테이블이 숨겨져있기 때문에 알 수 없는 쿼리가 실행됨
- 극복 : JPA에 위임하지 말고 중간엔티티를 생성해서 ManyToOne - OneToMany로 연결하면 좋다.
6. 상속관계 매핑
> RDB에는 객체와 다르게 상속 개념이 없지만, 어느정도 유사한 슈퍼타입 서브타입 관계라는 모델링 기법이 있다.
> 슈퍼타입 서브타입 논리모델을 실제 물리모델로 전환하는 방법
- 조인 전략(정석) : 각각 테이블로 변환
- @Inheritance(strategy = InheritanceType.JOINED)
- 가장 정규화된 방식이며, 객체 상속 모델과 유사함
- 장점 : 설계가 깔끔하고 저장공간 효율화
- 단점 : 조회 시 조인을 많이 사용하므로 복잡도 증가 -> 큰 단점 아님
- 단일 테이블 전략 : 한 테이블이 모든 컬럼을 포함
- default, @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
- 장점 : 조회 쿼리가 단순하고 조회 성능이 좋음
- 단점 : null을 허용해야 함
- 구현 클래스 별 테이블 전략 : 서브타입 테이블로 변환
- @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
- 검색 시 비효율 발생 가능성 있음
- 안쓰는게 좋음
7. @MappedSuperclass(매핑관계 상속)
> 공통 매핑 정보가 필요할 때 사용 (공통 속성)
- ex) 모든 엔티티는 DB에 값을 저장할 떄 마다 저장시점과 주체를 저장해야하는 룰이 있는 경우
> 활용방법
- 공통 매핑 정보를 갖는 클래스(BaseEntity)를 만들고 @MappedSuperclass어노테이션 붙임
- 공통 매핑정보를 가질 엔티티들은 BaseEntity를 상속받는다.(extends)
> 특징
- 엔티티가 아니므로 테이블과 매핑되지 않는다.
- 자식클래스에 상속정보를 보내지 않으므로 자식클래스 객체를 부모타입으로 조회할 수 없다.
- 추상클래스 사용 권장
'공부 > Java' 카테고리의 다른 글
Hibernate(7) - 값 타입 (0) | 2019.11.22 |
---|---|
Hibernate(6) - 프록시, 즉시/지연 로딩, 연관관계 관리 (0) | 2019.11.22 |
Hibernate(4) - 엔티티 매핑 (0) | 2019.11.20 |
Hibernate(3) - JPA 영속성 컨텍스트, 플러시, 준영속 상태 (0) | 2019.11.20 |
Hibernate(2) - JPA 기본 CRUD 연습 (0) | 2019.11.19 |