테이블에서 항상 다 쪽에 외래키가 존재함 -> 객체와 테이블의 차이 때문에 일대다를 쓴다면 외래키를 다른 테이블이 관리하게 됨
@JoinColumn 을 사용하지 않으면 조인 테이블 방식을 이용하게 됨. ( 중간에 테이블 하나 추가 )
@OneToMany 로 매핑한 곳에 @JoinColumn 을 추가하면 테이블에서는 반대 쪽에 FK가 생긴다.
양방향은 공식적으로 존재하지 않음. 만약 쓴다면 @JoinColumn (insertable=false, updatable=false)를 사용한다.
그냥 다대일 양방향 쓰자
일대일 (OneToOne)
일대일은 주 테이블 ( 많이 엑세스하는 테이블 ) 혹은 대상 테이블 중에 외래키 선택 가능하다.
외래키에 유니크 제약조건을 추가한다 (일대일이니까!)
주 테이블에 외래키
객체 지향 개발자들이 선호함. JPA 매핑 편리
장점 : 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
단점 : 값이 없으면 외래키에 NULL 허용
대상 테이블에 외래키
전통적인 데이터베이스 개발자들이 선호함
장점 : 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경시 테이블 구조 유지
단점 : 프록시 기능의 한계로 지연로딩 해도 즉시로딩된다. ( 대상 테이블로 쿼리를 날려봐야 존재하는지 안하는지 파악할 수 있기 때문에 쿼리를 바로 날림 )
실무에서는 주로 주 테이블에 외래키를 쓰는 전략을 사용한다. ( DBA와 협의 )
다대다 (ManyToMany)
쓰지마라
차라리 중간 테이블을 엔티티로 만들고 OneToManyManyToOne을 사용하자
주요 속성 정리
@JoinColumn
외래키를 매핑할 때 사용
속성
name : 매핑할 외래키 이름 (default : 필드명_참조하는 테이블의 기본키 컬럼명)
referecnedColumnName : 외래 키가 참조하는 대상 테이블의 컬럼명 (참조하는 테이블의 기본키 컬럼명)
foreignKey(DDL) : 외래키 제약조건을 직접 지정 가능. 테이블 생성할 때만 사용
unique, nullabel, insertable, updatable, columnDefinition, table 등
@ManyToOne
다대일 관계 매핑
속성
optional : false로 설정 시 연관된 엔티티가 항상 존재해야함. (default : true)
fetch : 글로벌 페치 전략 설정 (default: FetchType.EAGER)
cascade : 영속성 전이 기능 사용
@OneToMany
다대일 관계 매핑
속성
mappedBy : 연관관계의 주인 필드를 선택
fetch : 글로벌 페치 전략 설정 ( default: FetchType.LAZY)
cacade
고오급 매핑
상속관계 매핑
조인 전략 (JOINED)
단일 테이블 전략 (SINGLE_TABLE, default)
구현 클래스마다 테이블 전략 (TABLE_PER_CLASS)
주요 어노테이션
@Inheritance(starategy = InheritanceType.XXX)
JOINED : 조인 전략
SINGLE_TABLE : 단일 테이블 전략 ( JPA 기본 전략 )
TABLE_PER_CLASS : 구현 클래스마다 테이블 전략
@DiscriminatorCloumn(name="DTYPE")
구별하기 위한 타입 정보를 넣어준다. 웬만하면 넣어주는 것이 좋다.
부모 클래스에 넣어준다.
@DiscriminatorValue('XXX')
자식 클래스에 넣어주어 DTYPE에서 보여질 값을 넣어준다.
위 예제에서 만약 Album을 A, Movie를 M, Book을 B로 식별하게 하고싶다면 부모 클래스에 @DiscriminatorCloumn(name="DTYPE") 를 걸어주고 자식 클래스 하나하나마다 @DiscriminatorValue('A')@DiscriminatorValue('M')@DiscriminatorValue('B')를 각각 걸어주어 DTYPE에 표기될 구별 이름을 설정하게 해준다.
만약 부모 클래스를 사용하지 않는다면 abstract class 로 만든다.
만약 부모클래스를 사용한다면 그냥 class로 Entity화 한다.
조인전략
장점
테이블이 정규화 되어있다.
외래키 참조 무결성 제약조건을 활용가능하다?
저장공간의 효율화가 가능하다 <- 아마 필요한 값들만 저장할 수 있어서 그런듯?
단점
조회 시 조인을 많이 사용해서 성능 저하 발생
조회 쿼리가 복잡함
데이터 저장시 INSERT 쿼리를 두번 호출
관리 테이블이 많아짐
단일 테이블 전략
장점
조인이 필요 없어 일반적으로 조회 성능이 빠름
조회 쿼리가 단순 ( 그냥 테이블 조회하면 됨 )
단점
자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야함
단일 테이블에 모든 것을 저장하므로 테이블이 커질 가능성이 존재.
상황에 따라서는 오히려 조회 성능이 느려질 수 있다. <- 어떤 상황이지?
구현 클래스마다 테이블 전략
이 전략은 데이터베이스 전문가와 개발자 모두 추천하지 않는 방식
넘어가자
상속매핑 정리
기본적으로 JOIN 전략 사용 ! 엄청 단순한 경우 단일 테이블 전략 사용
@MappedSuperclass
공통의 매핑 정보가 필요할 때 사용
주로 id, name 혹은 생성일, 수정일 이런 공통 필드를 넣고 싶을때 일일히 넣지 않고 상속을 이용하는 방식
다양한 연관관계 매핑
다대일 (
ManyToOne
)mappedBy
써서 연관관계 주인의 객체와 연결일대다 (
OneToMany
)1 방향에서 연관관계의 주인이 되는 상황 ( 권장하지 않음 )
@JoinColumn
을 사용하지 않으면 조인 테이블 방식을 이용하게 됨. ( 중간에 테이블 하나 추가 )@OneToMany
로 매핑한 곳에@JoinColumn
을 추가하면 테이블에서는 반대 쪽에 FK가 생긴다.양방향은 공식적으로 존재하지 않음. 만약 쓴다면
@JoinColumn (insertable=false, updatable=false)
를 사용한다.그냥 다대일 양방향 쓰자
일대일 (
OneToOne
)일대일은 주 테이블 ( 많이 엑세스하는 테이블 ) 혹은 대상 테이블 중에 외래키 선택 가능하다.
외래키에 유니크 제약조건을 추가한다 (일대일이니까!)
주 테이블에 외래키
대상 테이블에 외래키
실무에서는 주로 주 테이블에 외래키를 쓰는 전략을 사용한다. ( DBA와 협의 )
다대다 (
ManyToMany
)OneToMany
ManyToOne
을 사용하자주요 속성 정리
@JoinColumn
@ManyToOne
@OneToMany
고오급 매핑
상속관계 매핑
주요 어노테이션
@Inheritance(starategy = InheritanceType.XXX)
@DiscriminatorCloumn(name="DTYPE")
@DiscriminatorValue('XXX')
@DiscriminatorCloumn(name="DTYPE")
를 걸어주고 자식 클래스 하나하나마다@DiscriminatorValue('A')
@DiscriminatorValue('M')
@DiscriminatorValue('B')
를 각각 걸어주어 DTYPE에 표기될 구별 이름을 설정하게 해준다.abstract class
로 만든다.조인전략
장점
단점
단일 테이블 전략
장점
구현 클래스마다 테이블 전략
상속매핑 정리
@MappedSuperclass
주로 id, name 혹은 생성일, 수정일 이런 공통 필드를 넣고 싶을때 일일히 넣지 않고 상속을 이용하는 방식
public class Member extends BaseEntity
와 같이 상속한다. 그러면 기존 매핑정보에 추가됨