JPA(Java Persistence API)란 무엇이며, 왜 사용하는가?
JPA(Java Persistence API)란?
자바 애플리케이션에서 관계형 데이터베이스를 객체 지향적으로 다룰 수 있도록 하는 ORM(Object-Relational Mapping) 표준 인터페이스
JPA 사용하는 이유?
ORM이란?
JPA 영속성 컨텍스트의 이점(5가지)을 설명
영속성 컨텍스트란?:
영속성 컨텍스트를 쓰는 이유?
1. 1차 캐시: 조회가 가능하며 1차 캐시에 없으면 DB에서 조회하여 1차 캐시에 올려 놓습니다.
2. 동일성 보장: 동일성 비교가 가능합니다.(==)
3. 쓰기 지연: 트랜잭션을 지원하는 쓰기 지연이 가능하며 트랜잭션 커밋하기 전까지 SQL을 바로 보내지 않고 모아서 보낼 수 있습니다.
4. 변경 감지(Dirty checking): 스냅샷을 1차 캐시에 들어온 데이터를 찍습니다. commit 되는 시점에 Entity와 스냅샷과 비교하여 update SQL을 생성합니다.
5. 지연 로딩: 엔티티에서 해당 엔티티를 불러올 때 그 때 SQL을 날려 해당 데이터를 가져옵니다.
JPA와 JPQL은 무슨 관계?
JPQL: Java Persistence Query Language의 약자로, DB 테이블이 아닌 엔티티의 객체를 대상으로 검색하는 객체 지향 쿼리입니다.
JPA: JPQL을 읽고 분석해서 SQL을 생성한 후 DB에 SQL을 실행하는 일을 합니다.
JPA는 특정 DB에 의존하지 않아 여러 DB에도 동일한 JPQL을 사용하면 DB에 접근할 수 있습니다. (Dialect - 방언만 변경하면 JPQL 수정 없이 DB 변경 가능)
=> 정리) JPA를 사용하기 위해 Repository 인터페이스를 만들고, JpaRepository를 상속받습니다.
여기에서 정의한 인터페이스 메서드를 실행하여 DB 연동을 하는데요.
이때, JPA는 인터페이스 메서드 이름을 분석해서 JPQL로 변환하고, 이를 가지고 SQL을 만들어서 DB에 SQL을 실행하는 과정을 합니다.
JPA Propagation 전파단계를 설명
JPA Propagation : 트랜잭션 동작 도중 다른 트랜잭션을 호출(실행)하는 상황에 선택할 수 있는 옵션
JPA를 쓴다면 그 이유에 대해서 설명
N + 1 문제는 무엇이고 이것이 발생하는 이유와 이를 해결하는 방법
N+1문제: 하나의 쿼리를 실행할 때 추가로 N개의 쿼리가 실행되는 문제
즉시 로딩과 지연 로딩 전략 각각의 상황에서 발생할 수 있다.
즉시 로딩에서 발생하는 이유? : JPQL을 사용하는 경우 전체 조회를 했을 때, 영속성 컨텍스트가 아닌 데이터베이스에서 직접 데이터를 조회한 다음 즉시로딩 전략이 동작하기 때문
지연 로딩에서 발생하는 이유? : 지연로딩 전략을 사용한 하위 엔티티를 로드할 때, JPA에서 프록시 엔티티를 unproxy 할 때 해당 엔티티를 조회하기 위한 추가적인 쿼리가 실행되어 발생
해결 방법
1. FetchJoin 사용하는 방법 : JPQL의 join fetch를 사용. JPQL에서 성능 개선 및 최적화를 위해 제공하는 기능으로 연관된 엔티티나 컬렉션을 함께 한 번에 조회하는 역할을 한다. (Inner Join)
(일반 조인은 패치 조인과는 다르게 오직 지정된 SELECT 결과만 가져올 수 있고, 연관 엔티티나 컬렉션을 함께 가져오지 못합니다.)
2. @EntityGraph를 사용하는 방법 : @EntityGraph의 attributePaths에 같이 조회할 연관 엔티티명을 적으면 됩니다. ,(콤마)를 통해 여러 개를 줄 수도 있습니다.(Outer join)
Fetch Join과 EntityGraph 사용 시 주의할 점이 있나?
FetchJoin과 EntityGraph는 공통적으로 카테시안 곱(Cartesian Product) 이 발생 하여 중복이 생길 수 있습니다.
Q. 카테시안 곱이란? : 두 테이블 사이에 유효 join 조건을 적지 않았을 때 해당 테이블에 대한 모든 데이터를 전부 결합하여 테이블에 존재하는 행 갯수를 곱한만큼의 결과 값이 반환되는 것
해결 방법?
1. JPQL에 DISTINCT 를 추가하여 중복 제거
2. OneToMany 필드 타입을 Set으로 선언하여 중복 제거
즉시 로딩(Eager Loading)과 지연 로딩(Lazy Loading)의 차이점
즉시 로딩 (Eager Loading): 연관된 엔티티를 즉시 조회하는 방식
지연 로딩 (Lazy Loading): 실제로 접근할 때만 데이터를 조회하는 방식 (권장)
JPA와 트랜잭션- JPA에서 트랜잭션이 필요한 이유
Q. @Transactional의 주요 특징은?
1. 읽기 전용 트랜잭션 (readOnly = true)
@Transactional(readOnly = true)
public List<User> getUsers() { ... }
동작방식
장점
1. 불필요한 flush() 호출 제거
• 변경 감지(Dirty Checking) 수행 X
• SQL UPDATE 또는 INSERT 쿼리 실행 방지
2. JDBC Connection 최적화
• Connection.setReadOnly(true) 설정으로 DB의 성능 최적화
• 일부 데이터베이스(MySQL, PostgreSQL 등)에서는 읽기 전용 트랜잭션이 더 빠르게 동작
3. 트랜잭션 격리 수준 최적화
• SET TRANSACTION READ ONLY; 설정으로 데이터 무결성 보호
• 쓰기 작업이 차단되어 성능 부담 감소
2. 트랜잭션 롤백 (rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class)
public void updateUser() { ... }
JPA 캐싱 - JPA의 1차 캐시와 2차 캐시 차이점?
1차 캐시(First-Level Cache)란?
2차 캐시 (Second-Level Cache)란?
1. 1차 캐시 (기본 제공)
• EntityManager 단위에서 관리 (세션 범위)
• 동일한 트랜잭션 내에서 같은 엔티티를 조회하면 캐시에서 반환됨
2. 2차 캐시 (옵션, 설정 필요)
• 애플리케이션 전역에서 엔티티를 캐싱하는 기능
• ehcache, Hazelcast 등의 구현체를 사용하여 캐싱 가능