JPA
자바 ORM 기술 표준으로 객체와 관계형 데이터베이스를 매핑하는 기술
- ORM (객체-관계 매핑)
- 자바 객체와 데이터베이스 테이블을 자동으로 매핑
- @Entity, @Table 등의 어노테이션을 통한 매핑 설정
- 쿼리 메서드
- 메서드 이름으로 쿼리 자동 생성
- 복잡한 쿼리는 @Query 어노테이션으로 처리
- 지연 로딩(Lazy Loading)
- 연관된 엔티티를 실제 사용하는 시점에 로딩
- 프록시 객체를 통한 성능 최적화
- 지연 로딩과 즉시 로딩
- @ManyToOne, @OneToMany 등의 관계 설정
- 성능 최적화를 위한 로딩 전략 선택
영속성 컨텍스트
엔티티의 CRUD를 담당하면서 저장했거나 불러온 엔티티를 기억하는 1차 캐시 역할을 한다.
- 1차 캐시
- 영속성 컨텍스트 내부에 엔티티를 보관
- 동일 트랜잭션 내에서 반복 조회 시 DB 접근 없이 캐시에서 조회
- 동일성 보장
- 같은 엔티티를 반복 조회해도 동일한 객체 참조 반환
- 트랜잭션 범위의 repeatable read 보장
- 변경 감지(Dirty Checking)
- 엔티티의 변경사항을 자동으로 감지
flush 발생 시 entity와 스냅샷을 비교한다. 스냅샷은 처음 db에서 읽어왔을 때의 내용 - 바뀐 내용이 있으면 쓰기 지연 SQL 저장소에서 update 쿼리를 작성하여 트랜잭션 커밋 시점에 변경된 엔티티를 DB에 자동 반영
- 쓰기 지연
- 쓰기 지연 SQL 저장소가 존재
- entity 분석 후 insert 쿼리를 생성하고 쓰기 지연 SQL 저장소에 쌓은 뒤 commit 하는 순간 쿼리들이 flush 되면서 DB로 날아감
- flush 하는 방법
- em.flush()
- 트랜잭션 commit 시 자동 호출
- JPQL 쿼리 실행 시 자동 호출
- 엔티티의 생명 주기
- 비영속(new/transient): 영속성 컨텍스트와 관련 없는 상태
- 영속(managed): 영속성 컨텍스트에서 관리되는 상태
- 준영속(detached): 영속성 컨텍스트에서 분리된 상태.
- detach(entity): 엔티티를 영속성 컨텍스트에서 분리
- clear(): 영속성 컨텍스트를 비움
- close(): 영속성 컨텍스트를 종료
- 삭제(removed): 영속성 컨텍스트와 DB에서 삭제되도록 예약된 상태. 최종적으로 모두 삭제된다
준영속과 비영속의 차이점
비영속 상태는 식별자가 있을 수도 없을 수도 있지만 준영속 상태의 경우 식별자가 반드시 존재한다.
- 비영속 상태에서는 entity 객체 생성 시 id를 초기화하지 않았으므로 식별자가 없다.
- 만약 개발자가 초기 entity객체 생성 시 직접 id를 초기화해 생성하면 EntityManage는 비영속이 아닌 준영속 상태로 간주한다.
- 즉 준영속 상태는 내부 HashMap에 같은 식별자를 갖는 Entity 가 존재하지 않지만, Entity 에는 식별자가 있는 모든 경우를 의미한다.
- 이런 경우 비영속임에도 불구하고 persist 뿐만 아니라 merge 메서드도 가능하다
장점
- 생산성 향상: SQL 쿼리 작성 최소화
- 유지보수성: 객체지향적인 코드 작성 가능
- 데이터베이스 독립성: 다양한 DB 벤더 지원
복잡한 쿼리나 성능이 중요한 경우에는 네이티브 SQL이나 QueryDSL를 함께 사용하는 것이 좋음
트러블 슈팅
- N+1 쿼리 문제: 한 번의 조회로 가져온 엔티티 컬렉션에서 지연 로딩으로 관련 엔티티를 반복적으로 조회할 때 발생
- 해결 방법
- @EntityGraph 사용
- fetch join을 활용한 JPQL 사용
- @BatchSize 설정으로 in 쿼리 사용
- 해결 방법
- 성능 문제
- 비효율적 쿼리 생성: JPA가 쿼리를 생성하므로 항상 최적화된 쿼리는 아님
- 대량 데이터 처리 시 메모리 초과
- JPQL UPDATE, DELETE 문 사용
- EntityManager.clear()로 캐시 관리
- Lazy Loading, Eager Loading으로 인한 문제: 로딩 방법을 잘못 사용하면 성능 문제가 야기될 수 있음
- Dirty Checking: 과도한 변경 감지로 불필요한 업데이트가 발생할 수 있음. 필요한 부분만 수정하거나 변경 감지를 비활성화
JPA vs MyBatis
JPA | MyBatis |
ORM 기반 | SQL 매핑 프레임워크 기반 |
객체 지향적 접근 자동화된 SQL 생성 변경 감지 |
직접적인 SQL 제어 복잡한 쿼리 작성이 유연 |
복잡한 쿼리에서 제한적일 수 있음 | 더 많은 매핑 코드 작성 필요 |
객체 지향적인 설계가 중요한 프로젝트일 때 사용 | 데이터베이스 중심 설계나 복잡한 쿼리 사용이 필요한 경우 사용 |
728x90
반응형
'Java & Kotlin > Spring' 카테고리의 다른 글
Spring @Transaction (0) | 2025.01.14 |
---|---|
Spring Filter & Interceptor (0) | 2025.01.13 |
Spring Boot AutoConfiguration (0) | 2025.01.11 |
Spring Framework? (0) | 2025.01.10 |