본 내용은 김영한님의 실전 스프링 부트 JPA 활용 강의를 수강하며 정리한 내용입니다.
가급적 Setter를 지양해라
- Setter가 모두 열려있으면, 변경 포인트가 너무 많아져서 유지 보수가 어렵다.
모든 연관관계는 지연로딩(LAZY)으로 설정해라(중요)
-
즉시로딩(
Eager
)의 경우 N+1 문제가 발생 할 수 있다. -
어떤 SQL이 실행될지 추적하기 어렵다.
-
실무에서 모든 연관관계는 지연로딩(
LAZY
)로 설정해야 한다. -
함께 조회해서 가져오고 싶은 경우 fetch join 또는 엔티티 그래프 기능을 사용해야한다.
-
xxxToOne
어노테이션은 기본값이 Eager이기 때문에 LAZY로 바꿔줘야한다.
컬렉션은 필드에서 초기화 하자.
-
필드에서 바로 초기화 하는것이 안전하다.
-
null
에 대해 안전하다. -
하이버네이트에서는 엔티티를 영속화 할 때, 컬렉션을 감싸서 하이버네이트가 제공하는 내장 컬렉션으로 변경한다.
만약 getOrders()처럼 임의의 메소드에서 컬렉션을 잘못 생성하면 하이버네이트 내부 메커니즘에 문제가 발생할 수 있다.
Member member = new Member();
System.out.println(member.getOrders().getClass());
em.persist(member);
System.out.println(member.getOrders().getClass());
//출력결과
class java.util.ArrayList
class org.hibernate.collection.internal.PersistentBag
테이블, 컬럼명 생성 전략
스프링부트에서 하이버네이트의 기존 네이밍 전략 = SpringPhysicalNamingStrategy
스프링 부트 신규 설정(엔티티(필드) -> 테이블(컬럼))
- 카멜 케이스 -> 언더스코어 (memberId -> member_id)
- . (점) -> _(언더스코어)
- 대문자 -> 소문자
양방향 연관관계 메소드 작성
데이터를 양쪽에 저장해야 참조해서 값을 불러올 수 있다.
public static void main(String[] args){
Member member = new Member();
Order order = new Order();
member.getOrders().add(order);
order.setMember(member);
}
이런식으로 매번 작성해야 한다면, 번거롭기도하고 실수하기 딱 좋다.
그래서 아예 연관관계 메소드를 작성하자.
package com.jpabook.jpashop.domain;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "orders")
@Getter @Setter
public class Order {
@Id
@GeneratedValue
@Column(name = "order_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "delivery_id")
private Delivery delivery;
private LocalDateTime orderDate; //주문시간
@Enumerated(EnumType.STRING)
private OrderStatus status; //주문상태 [ORDER, CANCEL]
/* 연관관계 메소드*/
public void setMember(Member member){
this.member = member;
member.getOrders().add(this);
}
public void addOrderItem(OrderItem orderItem){
orderItems.add(orderItem);
orderItem.setOrder(this);
}
public void setDelivery(Delivery delivery){
this.delivery = delivery;
delivery.setOrder(this);
}
}
'JPA' 카테고리의 다른 글
[JPA] 이메일 인증 토큰 값이 Null ?? (EntityLifeCycle, Transactional) (0) | 2020.07.14 |
---|---|
[JPA] spring data jpa Page vs Slice (0) | 2020.06.29 |
[JPA] 변경 감지(dirty checking)와 병합(merge) (0) | 2020.05.02 |
[JPA] auto-increment 테스트 실패 원인 및 해결 (0) | 2020.03.03 |
[JPA] Entity의 LifeCycle (0) | 2020.03.03 |
댓글