본문 바로가기
기록/인프런

실전! 스프링 부트와 JPA 활용1 - 도메인 분석 설계

by 신발사야지 2023. 4. 27.

 

연관관계의 주인은 왜 중요한건가

 

외래키가 있는 곳을 연관관계의 주인으로 정해라.

연관관계의 주인은 단순히 외래 키를 누가 관리하냐의 문제이지, 비즈니스상 우위에 있다고 주인으로 정하면 안된다.

예를 들어서 자동차와 바퀴가 있으면, 일대다 관계에서 항상 다쪽에 외래키가 있으므로 외래키가 있는 반퀴를 연관관계의 주인으로 정하면 된다.

 

FK 꼭 넣어야 되요?

 

대용량 처리 → FK 안 거는게 낫다(index만 잘 걸면 된다)

돈과 같이 정합성이 엄청 중요하다 → FK 거는게 낫다

 

 

실무에서는 @ManyToMany 절대 쓰지마라

 

@Enumerated(EnumType.STRING) Enum 은 무조건 이걸로,

왜냐면 EnumType.ORDINAL로 하면 중간에 Enum 값 넣을 수 없으므로

 

엔티티 설계시 주의점

엔티티에는 가급적 Setter를 사용하지 말자

Setter가 모두 열려있다면 변경포인트가 너무 많아서 유지보수가 어렵다.

모든연관관계는 지연로딩으로 설정!(엄청중요, 외워라)

즉시로딩 (EAGER) 은 예측이 어렵고, 어떤 SQL이 실행될지 추적이 어렵다.

특히 JPQL을 실행할 때 N+1 문제가 발생할 수 있다.

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "member_id")
private Member member;

/*
em.find() 해서 order 를 찾으면 1건 찾으니까 member 를 같이 찾아오는데
JPQL 로 select * From order o; 이렇게 해서 조회를 하면
order 100건이 조회된다고 했을 때 member 가 fetch = FetchType.EAGER 로 설정되어 있으므로
100건의 member 를 찾기 위해서 단방향 쿼리 100건이 날라가 버린다. (N+1) 문제
EAGER 의 뜻은 JOIN 해서 가져오겠다는게 아니라 item 을 조회하면 무조건 member 값을 가져오겠다는 것
*/

실무에서 모든 연관관계는 지연로딩(LAZY) 로 설정해 둔다.

 

연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용한다.

 

**OneToOne, ManyToOne 관계는 기본이 즉시 로딩이므로 직접 지연로딩으로 설정해야 한다.

(이거 굉장히 조심하셔야 합니다.) xxToOne 은 무조건 FetchType을 LAZY 로

 

컬렉션은 필드에서 바로 초기화 하는게 안전하다.

@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems = new ArrayList<>();
  1. 초기화에 대해서 고민할 필요 없다.
  2. Hibernate 가 Entity 를 persist 하는 순간 Collection 을 한번 감싸버려요(지가 내부에서 지지고 볶아버려요) 자기가 사용하는 Collection 타입으로 바꿔버려요
  3. 가급적이면 Collection 값을 수정하지 마세요. 있는걸 그대로 써버리세요. 그게 가장 안전합니다. 하이버네이트가 관리하는 객체로 바뀌었기 때문에 값을 바꿔버리면 하이버네이트가 사용하는 메커니즘이 작동하지 않을 수 있습니다.

 

SpringPhysicaNamingStrategy

  1. 카멜케이스 → 언더스코어
  2. . → _
  3. 대문자 → 소문자

orderDate → order_data

 

NamingRule 은 직접 구현할 수도 있음

 

논리명 : 이름을 직접 명시하지 않았을 때

물리명: 모든 컬럼에 적용되는 법칙

 

 

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)

기본적으로 persist 는 entity 마다 해줘야 함

 

persist(orderItemA)

persist(orderItemB)

persist(orderItemC)

persist(orderA)

 

→ CascadeType.ALL 하면 persist(orderA) 하면 끝