개발일기/Spring

JPA (Java Persistence API)

길동이이이잉 2024. 4. 30. 00:36
728x90
반응형

※ persistence - 영속성

 

자바 진영의 ORM 기술 표준으로 인터페이스의 모음(즉, 실제로 동작하는 것이 아님),

JPA 인터페이스를 구현한 대표적인 오픈소스가 Hibernate.

 

ORM(Object Relational Mapping) - 객체 관계 매핑
객체와 데이터베이스의 관계를 매핑
객체는 객체대로 설계하고, 관계형 데이터베이스는 관계형 데이터베이스대로 설계
MVC 패턴에서 모델을 기술하는 도구, 객체와 모델 사이의 관계를 기술하는 도구
JPA는 ORM 프레임워크 중 하나
- 사용하는 이유 : 데이터베이스 접근을 프로그래밍 언어의 관점에서 맞출 수 있고, 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결함, SQL 문을 직접 작성하지 않고 엔티티를 객체로 표현 가능 등

Hibernate
ORM 프레임워크 (open source SW)
’Gavin King’과 시러스 테크놀로지스 출신 동료들이 EJB2 스타일의 Entity Beans 이용을 대체할 목적으로 개발

EJB
과거의 자바 표준( Entity Bean ), 과거의 ORM
단점 : 코드가 매우 지저분, API 복잡성이 높다(인터페이스를 많이 구현해야 함), 속도 느림

 

 

등장 배경

  • 객체와 관계형 데이터베이스 간의 패러다임 불일치
    • 객체 모델과 관계형 데이터베이스 모델은 지향하는 목적이 상이함
      • 객체 지향 언어의 추상화, 상속, 다형성 등의 개념이 RDB에는 없음
      • RDB는 데이터 중심으로 구조화 되어 있음
    • 객체 지향 중심으로 설계할수록 이 패러다임의 간극 극대화
    • 객체 모델링보다 SQL에 의존적인 데이터 중심의 모델로 변화
  • 이러한 패러다임 불일치를 해결하고자 등장
더보기

객체 지향 프로그래밍의 장점

소프트웨어의 생산성 향상. → 상속을 통해 소프트웨어의 재사용이 용이하고, 캡슐화를 통해 유지보수가 쉽다.

대형 프로젝트에 적합 → 클래스 단위로 모듈화 개발로 업무 분담

실세계에 대한 쉬운 모델링. 소프트웨어에 요구되는 사항들을 객체들의 상호작용으로 묘사할 수 있다.

보안성 향상. 캡슐화 특징으로 실제 구현되는 부분을 외부에 드러나지 않도록 하여 정보를 은닉할 수 있다.

 

JPA를 사용하는 이유

1. SQL이 아닌 객체 중심으로 개발

2. 생산성

          ◎ 반복적인 CRUD의 자동화 (Creat, Read or Retrieve, Update, Delete or Destroy)

                      저장 : jpa.persist(member)

                       조회: Member member = jpa.find(memberId)

                       수정: member.setName("변경할 이름")

                       삭제: jpa.remove(member)

          ◎ 페이징 기능 지원

          ◎ DB 수정이 간편

3. 유지보수

3. 애플리케이션과 데이터베이스 간의 성능 향상

4. 객체와 RDB 간의 패러다임의 불일치 해결


엔티티 매니저 팩토리와 엔티티 매니저

※ Entity : database와 table과 매핑되는 객체

 

엔티티 매니저 = 엔티티를 저장하는 가상의 데이터베이스

  • 테이블과 매핑한 엔티티를 관리(저장, 수정, 삭제, 조회)하는 관리자
  • 엔티티 매니저는 필요할 때마다 엔티티 매니저 팩토리에서 생성한다. → 비용이 거의 들지 않음
  • 여러 스레드가 동시에 접근하면 동시성 문제가 발생하기 때문에, 스레드 간에 절대 공유되어서는 안 됨
  • 데이터베이스와 연결이 필요한 시점(ex. 트랜잭션을 시작할 때)에 커넥션을 얻어서 사용

 

엔티티 매니저 팩토리

  • 엔티티 매니저를 만드는 공장
  • 엔티티 매니저 팩토리는 하나만 생성하여 애플리케이션 전체에서 공유함.   공장 만들기, 비용이 많이 발생함

 

영속성 컨텍스트

  • Persistence Context = 엔티티를 영구 저장하는 환경
  • 엔티티 매니저로 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리.
  • 영속성 컨텍스트는 엔티티 매니저를 생성할 때 만들어짐
  • 영속성 컨텍스트에 저장하는 것을 영속화

엔티티 생명주기

  • 비영속 : 영속성 컨텍스트와 전혀 관계가 없는 상태
  • 영속 : 영속성 컨텍스트에 저장된 상태
  • 준영속 : 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 삭제 : 삭제된 상태

 

영속성 컨텍스트의 이점

  • 1차 캐시
    • 엔티티를 저장(영속화)하면 1차 캐시에 저장된다
    • 엔티티를 조회 시 1차 캐시에서 우선 찾는다.
    • 1차 캐시에 없으면 DB를 조회하고, 1차 캐시에 저장한다.
    • 조회 시 성능상의 이점
    • 영속 엔티티의 동일성 보장
  • 변경 감지
    • dirty checking : 엔티티가 변경되면 변경사항을 데이터베이스에 자동으로 반영한다. (jpa에는 update 메소드가 없음)
    • 엔티티를 영속성 컨텍스트에 저장할 때 현재 상태를 복사 = 스냅샷
    • flush 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾음
    • 변경된 엔티티가 있으면 수정 쿼리를 생성하여 쓰기 지연 저장소에 저장
    • 쓰기 지연 저장소의 SQL을 데이터베이스에 플러시하고 트랜잭션을 커밋

※ 변경 감지는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에서만 적용됨. 

    비영속, 준영속 상태에서는 아무리 엔티티 값을 변경해도 자동으로 반영되지 않음

 


주의 사항

 

트랜잭션

  • service 단에서 같은 트랜잭션으로 묶어줘야 함 (영속성 컨텍스트가 동작하는 기준은 트랜잭션이 일어난 시점)
    • 트랜잭션이 다르면 다른 영속성 컨텍스트를 사용
    • 참고 - 선언적 트랜잭션(@Transactional)을 사용하는 경우에 대한 예시
    • service class 상단에 읽기용 transeactional을 공통으로 선언 →  등록이나 수정이 일어나는 메소드에 @Transactional을 새로 부여하여 엔티티에 대한 변경이 가능하도록 함

연관관계 설정

  • @ManyToOne, @OneToOne인 XToOne 관계에서 패치 타입 설정은 LAZY(지연 로딩)로 해야 함. (default : EAGER = 즉시로딩)
    • EAGER로 되어 있을 시 성능 문제가 발생하는 주요 원인이 될 수 있음
      • N + 1의 문제 발생
        • EAGER는 즉시 로딩으로 연관관계 엔티티까지 함께 로딩함
        • 이때 '조회하는 쿼리' + '조회한 엔티티의 개수(N)' 만큼 연관 관계를 조회하는 쿼리가 동시에 실행됨
        • 조회 성능에 매우 치명적
  • LAZY로 설정해도 연관 엔티티의 하위 범위까지 탐색하게 되면 N + 1의 문제가 발생
    • 이를 해결하기 위해서는 fetch join을 사용

 

OSIV (Open Session In View)

  • 하이버네이트에서 사용하는 용어, JPA에서는 Open EntityManager In View라고 하는 게 맞지만 관례상 OSIV라고함
  • 직역 - view에서 session을 열어 놓는다 = jpa에서 영속성 컨텍스트를 데이터베이스 커넥션 시작 시점부터 api  response를 보낼 때까지 유지하는 것
    • 장점 : 뷰단에서 지연로딩을 사용하여 엔티티를 조회할 수 있음
    • 단점 : 데이터베이스 커넥션 유지 시간이 길기 때문에 트래픽이 많은 서비스에서는 커넥션이 모자랄 수 있음
  • 기본 설정 true, 실시간 트래픽이 중요한 어플리케이션이라면 false로 바꾸는 것을 권장
    • 컨트롤러에서는 영속성 컨텍스트를 사용할 수 없기 때문에, 컨트롤러에 지연로딩을 사용하는 코드가 있다면 Lazy Exception
    • service 또는 repository 계층에서 지연로딩 등 뷰에 필요한 엔티티를 미리 로딩해 두는 방법으로 수정 필요

 

728x90
반응형