JPA

[JPA] 엔티티 설계시 주의점

cornarong 2021. 11. 26. 22:50

엔티티 설계시 주의점

 

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

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

2. 모든 연관관계는 지연로딩(fetch = FetchType.LAZY)으로 설정하자 

즉시로딩은 특정 엔티티를 조회할 때(로딩될 떄) 연관된 모든 엔티티를 조회한다.

 

기본적으로 전부 지연로딩(LAZY)로 셋팅을 하고 필요에 따라 연관된 원하는 엔티티를 같이 조회할 경우 fetch join 또는 엔티티티 그래프로 최적화를 하는 것이 좋다

  • 즉시로딩(EAGER)은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵다 특히 JPQL을 실행할 떄 N+1 문제가 자주 발생한다
  • 실무에서는 모든 연관관계는 지연로딩(LAZY)로 설정해야 한다
  • 연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용한다
  • @xToOne(OnToOne, ManyToOne) 관계는 기본 패치 전략이 즉시로딩(EAGER)이므로 직접 지연로딩(LAZY) 설정을 해야한다 / @xToMany(OnToMany, ManyToMany) 관계는 기본 패치 전략이 지연로딩(LAZY)이다

@xToOne의 관계일 경우 단건만 조회하면 EAGER 전략이 합리적일 것 같지만 여러개를 조회하는 상황이 발생할 경우 N+1 문제가 발생한다 따라서 기본을 LAZY로 셋팅하는게 합리적이다


3. cascade를 사용하여 Persist를 전파하자 (영속성 전이)

상위 엔티티가 변경될 경우 상위 엔티티의 연관된 하위 엔티티 같이 변경을 전파 해주는 옵션이다

즉 특정 엔티티를 영속상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들 수 있다.

 

JPA Cascade Type

  • ALL : 하위 엔터티로 모든 작업을 적용
  • PERSIST : 하위 엔티티까지 영속성 적용
  • MERGE : 하위 엔티티까지 병합
  • REMOVE : 하위 엔티티까지 삭제
  • REFRESH : 하위 엔티티까지 인스턴스 값 새로고침
  • DETACH : 하위 엔티티까지 영속성 제거

4. 컬렉션은 필드에서 초기화 하자.

  • 컬렉션은 필드에서 바로 초기화 하는것이 안전하다
  • 'NULL'문제에서 안전하다
  • 하이버네이트는 엔티티를 영속화 할 때, 컬렉션을 감싸서 하이버네이트가 제공하는 내장 컬렉션으로 변경한다 만약 'getOrders()'처럼 임의의 메서드에서 컬렉션을 잘못 생성하면 하이버네이트 내부 메커니즘에 문제가 발생할 수 있다. 따라서 필드레벨에서 생성하는 것이 가장 안전하고 코드도 간결하다
Member member = new Member();
System.out.println(member.getOrders().getClass()); // 1번
em.persist(team);
System.out.println(member.getOrders().getClass()); // 2번

// 출력 결과
// class java.util.ArrayList
// class org.hibernate.collection.internal.PersistentBag

5. 테이블, 컬럼명 생성 전략

스프링부트에서 하이버네이트 기본 매핑 전략을 변경해서 실제 테이블 필드명은 다르다

 

하이버네이트 기존 구현 :

1. 엔티티의 필드명을 그대로 테이블의 컬럼명으로 사용 (SpringPhysicalNamingStrategy)


스프링 부트 신규 설정 :
1. 카멜 케이스 -> 언더스코어(memberPoint -> member_point)
2. .(점) -> _(언더스코어)
3. 대문자 -> 소문자

 

적용 2 단계
1. 논리명 생성: 명시적으로 컬럼, 테이블명을 직접 적지 않으면 ImplicitNamingStrategy 사용

spring.jpa.hibernate.naming.implicit-strategy

: 테이블이나, 컬럼명을 명시하지 않을 때 논리명 적용

 

2. 물리명 적용: 컬럼, 테이블 명이 적혀 있든 않든 적용되는 모든곳에 적용

spring.jpa.hibernate.naming.physical-strategy

: 모든 논리명에 적용됨, 실제 테이블에 적용 (username -> usernm 등으로 회사 룰로 바꿀 수 있다)

 

스프링 부트 기본 설정

spring.jpa.hibernate.naming.implicit-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.hibernate.naming.physical-strategy:
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

 

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 - 인프런 | 강의

실무에 가까운 예제로, 스프링 부트와 JPA를 활용해서 웹 애플리케이션을 설계하고 개발합니다. 이 과정을 통해 스프링 부트와 JPA를 실무에서 어떻게 활용해야 하는지 이해할 수 있습니다., 본

www.inflearn.com