728x90
연관관계 맵핑
- toString(), lombok 무한 루프 주의
- ex) Team - Member 연관관계가 있을 경우 Team.getMember.toString -> Member.getTeam.toString -> Team.getMember.toString -> Member.getTeam.toString -> Team.getMember.toString -> Member.getTeam.toString -> Team.getMember.toString -> Member.getTeam.toString -> 무한 반복됨
- Json 생성 라이브러리
- Controller에서 Entity 절대 반환 금지
- 무한루프 발생 가능성
- 엔티티 변경 시 API의 스펙 자체가 변경되어버림 (단순 값만 있는 DTO 변환 후 반환하는 방법 권장)
- Controller에서 Entity 절대 반환 금지
- 연관관계의 주인은 외래 키의 위치를 기준으로 정해야 함
연관관계 맵핑 어노테이션 & 옵션 정리
- 일대다 양방향 맵핑
/* Member.java */
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team
/* Team.java */
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
- 지연로딩
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TEAM_ID")
private Team team
@OneToMany, @ManyToMany는 기본 옵션값이 지연 로딩
- 즉시로딩
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TEAM_ID")
private Team team
즉시 로딩은 JPQL에서 N+1 문제를 일으킨다
@ManyToOne, @OneToOne은 기본 옵션 값이 즉시 로딩
연관관계 편의 메서드
/* Member.java */
public void changeTeam(Team team) {
// 중복 등록 방지
if (this.team != null) {
team.getMembers().remove(this);
}
this.team = team;
team.getMembers().add(this);
}
/* Team.java */
public void addMembers(Member member) {
this.members.add(member);
member.changeTeam(this);
}
CASCADE(영속성 전이)
- 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들도 싶을 때
(ex: 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장) - 영속성 전이는 연관관계를 매핑하는 것과 아무 관련이 없음
(엔티티를 영속화할 때 연관된 엔티티도 함께 영속화하는 편리함을 제공할 뿐) - 옵션 종류
- ALL: 모두 적용
- PERSIST: 영속
- REMOVE: 삭제
- MERGE: 병합
- REFRESH: REFRESH
- DETACH: DETAC
/* Order.java */
@OneToOne(fetch = FetchType.LAZY, cascade = ALL)
@JoinColumn(name = "DELIVERY_ID")
private Delivery delivery;
/* Delivery.java */
@OneToOne(mappedBy = "delivery", fetch = FetchType.LAZY)
고아 객체
- 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로보고 삭제하는 기능
- 참조하는 곳이 하나일 때 사용해야함!
- 특정 엔티티가 개인 소유할 때 사용
- @OneToOne, @OneToMany만 가능
- 개념적으로 부모를 제거하면 자식은 고아가 된다.
(따라서 고아 객체 제거 기능을 활성화 하면, 부모를 제거 때 자식도 함께 제거된다.
이것은 CascadeType.REMOVE처럼 동작한다)
/* OrderItem.java */
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ORDER_ID")
private Order order;
/* Order.java */
@OneToMany(mappedBy = "order", cascade = ALL, orphanRemoval = true)
private List<OrderItem> orderItems = new ArrayList<>();
영속성 전이 + 고아 객체, 생명주기
- CascadeType.ALL + orphanRemovel=true
- 스스로 생명주기를 관리하는 엔티티는 em.persist()로 영속화, em.remove()로 제거
- 두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명 주기를 관리할 수 있음
- 도메인 주도 설계(DDD)의 Aggregate Root개념을 구현할 때 유용
cascade(영속성 전이), 고아 객체 실무 사용 팁
- 모든 연관관계를 지연 로딩으로 구현
(@ManyToOne, @OneToOne은 기본이 즉시 로딩이므로 지연 로딩으로 변경)
728x90
'개발 지식 > JPA' 카테고리의 다른 글
Querydsl 기본 문법 정리 (0) | 2023.08.19 |
---|---|
H2 DB 최초 생성 시 not found 에러 처리 (0) | 2022.08.09 |