1. Entity에는 가급적 Setter를 사용하지 말자
Setter를 무분별하게 사용하게 되면 어디서 해당 값이 변경되었는지 추적하기가 어렵다.
변경 포인트가 너무 많아서, 유지보수가 어렵다.
Setter가 필요할 경우에는 추적하기 쉽도록 메서드를 따로 생성해주는것도 좋은 방법이다.
2. 모든 연관관계는 지연로딩으로 설정
즉시로딩( EAGER )은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵다.
특히 JPQL을 실행할 때 N+1 문제가 자주 발생한다. 실무에서 모든 연관관계는 지연로딩( LAZY )으로 설정한다.
연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용한다.
@XToOne(OneToOne, ManyToOne) 관계는 기본이 즉시로딩이므로 직접 지연로딩으로 설정해야 한다.
N+1문제
연관 관계에서 발생하는 이슈로 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 갯수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어오게 된다. 이를 N+1 문제라고 한다.
N+1문제는 왜 발생하는 것일까?
jpaRepository에 정의한 인터페이스 메서드를 실행하면 JPA는 메서드 이름을 분석해서 JPQL을 생성하여 실행하게 된다. JPQL은 SQL을 추상화한 객체지향 쿼리 언어로서 특정 SQL에 종속되지 않고 엔티티 객체와 필드 이름을 가지고 쿼리를 한다. 그렇기 때문에 JPQL은 findAll()이란 메소드를 수행하였을 때 해당 엔티티를 조회하는 select * from Owner 쿼리만 실행하게 되는것이다. JPQL 입장에서는 연관관계 데이터를 무시하고 해당 엔티티 기준으로 쿼리를 조회하기 때문이다. 그렇기 때문에 연관된 엔티티 데이터가 필요한 경우, FetchType으로 지정한 시점에 조회를 별도로 호출하게 된다.
* JPQL이란 플랫폼에 독립적인 객체지향 쿼리 언어입니다. 자바 코드에서 데이터베이스를 조회할 때 특정 SQL이나 저장 엔진에 종속되지 않게 도와줍니다.
3. 컬렉션은 필드에서 초기화 하자.
컬렉션은 필드에서 바로 초기화 하는 것이 안전하다.
- null 문제에서 안전하다.
- 하이버네이트는 엔티티를 영속화 할 때, 컬랙션을 감싸서 하이버네이트가 제공하는 내장 컬렉션으로 변경한다.
만약 getOrders()처럼 임의의 메서드에서 컬력션을 잘못 생성하면 하이버네이트 내부 메커니즘에 문제가 발생할 수 있다.
따라서 필드레벨에서 생성하는 것이 가장 안전하고, 코드도 간결하다.
'개발공부 > 개념정리' 카테고리의 다른 글
| Dispatcher Servlet (0) | 2022.06.23 |
|---|---|
| 트래픽 급증으로 장애가 발생하면 어떻게 대응해야 하나요? [Scale Up vs Scale Out] (0) | 2022.06.22 |
| [Java] String, StringBuffer, StringBuilder (0) | 2022.06.20 |
| 데드락(DeadLock) (0) | 2022.06.19 |
| TDD(Test-driven development) (0) | 2022.06.18 |