우선 인프런강의에서 진행하는 예제의 기능 및 요구사항은 다음과 같다
다음은 다이어그램이다
실제로 회원이 여러 상품을 구매할 수 있는 것 처럼 회원, 주문, 상품 간의 관계에서 일대다 혹은 다다대 관계를 확인 할 수 있다.
하지만 다대다 관계는 거의 사용하지 않으므로 주문상품이라는 엔티티를 추가해서 다대다가 아닌 일대다 관계로 풀어 냈다.
테이블로 표현을 하면 다음과 같다.
연관관계는 그림에서 새발표기법으로 표기를 잘 해놓았다.
왜래키 값을 업데이트할 때에는
일대다 일때 다 에 왜래키가 들어감
주인의 값이 바뀌면 왜래 키 값도 바꾼다.
왜래키 값을 가까운걸 주인으로 하는게 좋음
주인이라고해서 비즈니스 상 우위에 있는것은 아님
(member(주인)-> member_id(FK))
mappedBy="(~~)" 나는 ~~에 의해 매핑됨 =>읽기 전용으로 됨
Setter가 너무 많이 열려 있다면 변경포인트가 너무 많아 유지보수가 힘들다
즉시 로딩은 예측하기 쉽지 않고 하나를 로딩하면 연관되어 있는 다른 데이터까지 같이 로딩이 되기 때문에 (N+1문제 발생)
LAZY키워드를 사용해서 지연로딩으로 설정하는게 좋다.
fetch join을 사용하면 원하는 것만 가져올 수 있다.
Ex))Member에 26번째줄
private List orders =new ArrayList<>();
=>바로 초기화
public Member() {
orders= new ArrayList<>();
=>따로 초기화
}
따로 만들어서 초기화 하는것이 NULL 문제로 부터 자유롭다.
NULLPOINTEXCEPTION 날 일이 없고 , 컬랙션을 감싸서 hibernate가 제공하는 내장 컬렉션으로 변경한다
하지만 바로 초기화하면 hibernate가 추적하기위해 member 객체를 자신의 타입에 알맞게 바꾸는데
ex) class org.hibernate.collection.internal.PersistentBag
그러나 public Member() {
orders= new ArrayList<>(); =>따로 초기화
}
이런식으로 다시 초기화 해버리면 hibernate가 원하는 매커니즘 대로 동작하지 않아 문제발생할 우려가 있다.
부모 Entity를 persist할 때 자식 entity도 함께 persist 하고 싶을 때 이용한다.
이로 인해서 부모와 자식의 persist, remove 를 함께 관리할 수 있다.
또한 부모 entity 만으로 자식 entity들을 모두 컨트롤할 수 있다.
ex) persist(orderItemA)persist(orderItemB)persist(orderItemC)
persist(order)쓸 것을 만일 Cascade를 쓰면 persist(order)만 쓰면 된다.
각각 호출 해야하지만 한꺼번에 가능.
단, 반드시 Entity 서로 간의 단일 종속관계가 있을 때만 사용하고, 다른 Entity 와 복잡하게 매핑관계가 얽혀 있다면 사용하면 안된다.
양방향 관계일때 Member, Order의 경우 서로의 값을 세팅해 주기 위해 사용
예)
member.getOrders().add(order);
order.setMember(member);
↓
member.getOrders().add(this);
한 줄로 처리 가능
연관 관계의 주인의 반대쪽 필드는 mappedby를 설정하여 읽기 전용으로 쓰게 된다.
그런데 일대다 중 다 쪽에만 연관 관계를 설정하면 객체 지향적이지 않을뿐더러, DB에서 데이터를 조회하기 전까지는 일대다 중 다 쪽에만 값이 세팅되어 일 쪽 Entity에서는 연관 관계를 모르기 때문에 일 쪽의 값을 출력해보면 데이터가 나오지 않을 수 있다.