@OneToMany
@ManyToOne
@OneToOne
*임베디드 타입은 @Embeded
나 @Embeddable
으로 표현
@Inheritance(stragy = InheritanceType.JOINED)
✅ 자식 테이블들을 DTYPE으로 구분하여 사용할 수 있음.
✅ 상속받는 자식 테이블을 각각 만들고, 부모 테이블의 PK를 자식 테이블의 PK이자 FK로 사용함.
➡️ 이를 통해 다른 테이블에서 부모 테이블만 보도록 설계할 수 있음.
@Inheritance(stragy = InheritanceType.SINGLE_TABLE)
✅ 자식 테이블들을 통합한 단일 테이블로 사용할 수 있음.
✅ @DiscriminatorValue("...") = 각각의 테이블들이 하나의 싱글테이블로 합쳐지기에 DB에서 테이블을 식별할 수 있도록 구분할 수 있는 값을 넣어줘야 함.
@Inheritance(stragy = InheritanceType.TABLE_PER_CLASS)
✅ 자식 엔티티들을 각각의 테이블로 만들어 사용함.
✅ 여러 자식들을 조회할 때, UNION을 사용하여 성능이 저하되며 다른 여러 단점들이 존재하여 자주 사용 X
모든 연관관계에서 FetchType을 🔴 지연로딩(LAZY) 🔴 으로 설정해야 한다 !!
즉시로딩 (FetchType - EAGER) : 엔티티를 조회할 때 연관된 엔티티를 즉시 조인해서 값을 넣어주고, 함께 조회함.
◦ 단점 : 예상하지 못한 SQL이 발생하고, 굉장히 많은 문제를 발생시킬 가능성 존재
지연로딩 (FetchType - LAZY) : 엔티티를 조회할 때 연관된 엔티티를 조인하지 않음. 즉 값을 넣어주지 않는다.
대신, 연관된 엔티티를 참조할 때 조인 쿼리를 작성하여 값을 넣어준다.
(필요할 때 넣어준다는 뜻 !)
➡️ 해당 객체를 조회할 때 그 객체를 조회하는 쿼리가 발생하게 된다.
➡️ @...ToOne
의 경우, FetchType의 디폴트가 즉시로딩으로 되어있으므로
어떤 SQL이 실행될지 추적하기 어렵기 때문에 컬렉션은 null문제 해결을 보장하기위해 필드에서 초기화하는 것이 안전함.
(@OneTo...
의 디폴트는 LAZY이기에 따로 설정안해도 됨.)
데이터베이스에서 무조건 다(N)쪽이 외래 키(FK)를 갖는다 !!
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private Category parent;
@OneToMany(mappedBy = "parent")
private List<Category> child = new ArrayList<>();
CascadeType의 종류로는 ALL, PERSIST, REMOVE, MERGE, REFRESH, DETACH가 있으나 자주 사용하는 건 세 개 정도.
이는 엔티티를 영속화할 때 연관된 엔티티들도 함께 영속화해준다는 점에서 편리함을 제공하는 것이지,연관관계를 매핑하는 것과는 상관 ✖︎
ex)
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
컬렉션은 필드에서 바로 초기화 하는 것이 안전하다. (선언과 초기화를 같이 하자 !)
null
문제에서 안전하다.➡️ 따라서 필드레벨에서 생성하는 것이 가장 안전하고, 코드도 간결하다.
ex)
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
스프링 부트에서 하이버네이트 기본 매핑 전략을 변경해서 실제 테이블 필드명은 다름 !
스프링 부트 신규 설정
(엔티티(필드) ➡️ 테이블(컬럼))
@Enumerated(EnumType.STRING)
private DeliveryStatus status; //ENUM [READY(준비), COMP(배송)]
새로운 게 추가 되었을 때를 고려해줘야 하기 때문에,
EnumType은 꼭 스트링으로 해주기 !!