0. 매핑
개념
JPA에서는 엔티티에 연관관계를 매핑해두고 필요할 때 해당 엔티티와 연관된 엔티티를 사용하여 좀 더 객체지향적으로 프로그래밍 할 수 있도록 도와줍니다.
JPA 매핑 종류
- 일대일 (OneToOne)
- 일대다 (OneToMany)
- 다대일 (ManyToOne)
- 다대다 (ManyToMany)
방향
객체에서는 단방향과 양방향이 존재한다.
- 단방향
- 양방향
1. 일대 일 단방향 매핑
Cart.java (장바구니)
- 장바구니에서는 회원 엔티티를 일방적으로 참조한다
- 장바구니와 회원은 일대일로 매핑되어 있다.
😲 한개의 장바구니에 여러개의 회원이 있을 수 없다.
참조 형태
CartRepository.java ( 장바구니 저장 )
- 실제로 장바구니를 생성하고 Member ID가 어떻게 참조되는지 확인해보자
CartTest.java ( 장바구니 매핑 테스트)
- 결과를 보면 엔티티가 조회되면서 즉시 로딩되는걸 볼 수 있다. 일대일, 다대일 매핑의 경우 즉시 로딩을 기본 Fetch 전략으로 설정한다.
즉시로딩
- 엔티티 조회 시, 해당 엔티티와 매핑된 엔티티도 한번에 조회한다.
- 매핑할 때 FetchType.EAGER로 설정할 수 있다.
2. 다대일 단방향 매핑
CartItem.java ( 장바구니에 담길 아이템들 )
- 하나의 장바구니에는 여러개의 상품이 들어갈 수 있다.
- 또한 상품을 여러 개 주문할 수도 있다.
- 해당 관계에서는 여러개의 상품이 한개의 카트 혹은 한개의 아이템을 보고 있음으로 ManyToOne으로 설정해 준다.
현재까지의 구상도
3. 다대일 / 일대다 매핑
아이템, 멤버, 카트, 카트에 담길 것이 준비가 되었으니 주문 정보를 만들어야 한다.
- OrderStatus.java (enum) 설정
- 주문 상태는 주문, 주문 취소로 구분한다.
- Order.java (주문 정보 )
- 주문 정보에는 멤버의 ID, 주문번호 ID가 들어간다.
- 주문이 등록된 시간과 바뀐 시간을 검수한다.
주문에 들어간 ITEM ( OrderItem.java )
- 하나의 상품은 여러개의 주문 목록으로 들어갈 수 있다. 따라서 다대일 매핑을 수행한다.
- 한번의 주문에 여러개의 상품을 주문할 수 있음으로 주문 상품엔티티와 주문 엔티티를 다대일 방향 매핑을 먼저 설정한다.
4. 연관관계의 주종관계
여기서 주의사항, 객체를 양방향 매핑할 경우
- 연간 관계의 주인은 외래키가 있는 곳으로 설정
- 주인이 외래키를 관리
- 주인이 아닌 쪽은 매핑 시 mappedBy 속성을 사용
추가된 order 코드
- 외래키를 가지고 있는 Order이 주가 된다.
- Order은 주문한 ITEM을 여러개 가지고 있어야 함으로 List 형태로 OrderItem을 저장한다.
- 여기서 주는 order임으로 mappedBy를 사용한다
- Order에서만 외래키를 관리하고, 수정 및 삭제등을 할 수 있다.
- OrderItem에서는 읽기 권한만 존재한다고 보면 된다.
변경 시각화
5. 영속성 전이
영속성 전이
영속 전이는 엔티티의 상태를 변경할 때 해당 엔티티와 연관된 엔티티들에게 상태 변화를 전달하는 옵션이다. 이때 부모는 매핑에서 One에 해당하고 자식은 Many에 해당한다. 즉 Order 엔티티가 삭제되었을 때 해당 엔티티와 연관된 OrderItem 엔티티가 함께 삭제되거나 OrderItem 엔티티를 한번에 저장할 수 있다.
JPA 에서의 CASCADE 종류
JPA에서 지원하는 CASCADE 종류는 아래와 같습니다.
종류 | 설명 |
ALL | 모든 변경에 대해 적용 |
PERSIST | 영속 상태가 되었을 때 적용 |
MERGE | 병합할 때 적용 |
REMOVE | 삭제할 때 적용 |
REFRESH | 엔티티를 새로 고칠 때 적용 |
DETACH | 영속성 컨텍스트에서 분리할 때 적용 |
OrderRepository 를 추가하고 Order에 대하여 CASCADE.ALL 적용
- OrderRepository 추가
- 주문을 사용할 수 있다.
- CascadeType.ALL을 통하여 영속성 전이를 할 수 있다.
영속성 전이 test ( OrderTest.java )
- 아이템을 생성하고 주문을 생성, 주문 아이템을 등록한다.
- FLUSH를 통해 DB에 반영하고, 영속성 컨텍스트를 초기화 한다.
- 등록한 주문 정보와 DB 주문 정보를 비교해서 테스트를 진행한다.
6. 고아 객체
고아 객체?
부모 엔티티와 관계가 끊어진 자식 엔티티를 고아 객체라고 한다. 영속성 전의 기능과 같이 사용하여 자식 엔티티의 생명 주기에 관여할 수 있다. 다만 주의사항으로 해당 엔티티를 참조하는 엔티티가 두개 이상일 경우 이 기능을 사용하면 안된다.
Order.java
OrderTest.java - OrphanRemove Test
- 이렇게 되면 주문 엔티티에서 주문 상품에 대한 엔티티를 삭제했을 때 엔티티가 삭제되는것을 볼 수 있습니다.
7. 지연 로딩
지연로딩?
지연 로딩은 실제 엔티티 대신에 프록시 객체를 넣어둔다. 프록시 객체는 실제로 사용하기 이전에 로딩을 하지 않고, 실제 사용 시점에 조회 쿼리문이 실행된다.
지연로딩 테스트
- orderItem 조회를 위한 OrderItemRepository 생성
- 테스트 코드 작성 (orderTest)
- 해당 테스트를 실행하게 되면 한개의 동작을 수행했을 뿐인데 등장하는 엄청난 트랜잭션을 볼 수 있습니다.
- orderItem.java 지연로딩 설정
- FetchType.LAZY 를 설정해서 지연로딩을 설정한다.
로그를 보면 order item을 조회하는 쿼리만 실행되는 것을 볼 수 있다.
나머지 엔티티도 지연로딩 설정