본문 바로가기

framework/jpa

[JPA] JPA 사용 이유 및 개념 정리

JPA란?

  • Java Persistence API
  • 자바 진영의 ORM 기술 표준 
  • JPA는 애플리케이션과 JDBC 사이에서 동작한다.
  • 표준 명세이다
    • 인터페이스의 모음
    • JPA  표준 명세를 구현한 3가지 구현체
    • 하이버네이트, EclipseLink, DataNucleus

ORM이란?

  • Object relational mapping - 객체 관계 매핑
  • 객체는 객체대로 설계
  • 관계형 데이터베이스는 관계형 데이터베이스대로 설계
  • ORM 프레임워크가 중간에서 매핑
  • 대중적인 언어에는 대부분 ORM 기술이 존재한다.

JPA를 사용하는 이유

  • SQL 중심적인 개발에서 객체 중심으로 개발 : https://my-dev-record.tistory.com/12
  • 생산성 : 객체 중심으로 개발하게 되므로 매핑에 투자해야할 시간이 줄어든다.
  • 유지보수 : 객체에 필드가 추가되어도 SQL을 수정하지 않아도 된다.
  • 패러다임의 불일치 해결 (위에 링크한 곳에 설명한 문제들을 해결해준다.)
    • JPA와 상속
    • JPA와 연관관계
    • JPA와 객체 그래프 탐색
    • JPA와 비교하기
    • 패러다임의 불일치를 해결하여 신뢰할 수 있는 엔티티와 계층을 갖는다.
  • 데이터 접근 추상화와 벤더 독립성
  • 표준 

JPA 영속성 컨텍스트 설명 및 성능

  • JPA를 이해하는데 가장 중요한 언어
  • 엔티티를 영구 저장하는 환경이라는 뜻
  • Entitymanager.persist(entity);
  • persist는 DB에 저장하는 기능을 하지만, 영속성 컨텍스트를 통해서 이 엔티티라는걸 영속화하는 것이다.
  • 혹은 엔티티를 영속성 컨텍스트에 저장하는 것이다.
  • 영속성 컨텍스트는 논리적 개념
  • 눈에 보이지 않는다
  • 엔티티 매니저를 통해서 영속성 컨텍스트에 접근 

1차 캐시와 동일성 보장 내용 

동일한 트랜잭션에서만 보장된다.

영속성 컨텍스트에서 1차 캐시의 영역이 존재한다.

1차 캐시는 @Entity로 등록한 클래스의 @Id 필드를 키로 설정한다.

또한 @Entity 클래스의 인스턴스가 저장된다.

 

아래 코드 내용을 설명하면,

  1. 영속성 컨텍스트 1차 캐시 영역에 아무런 데이터가 없다.
  2. member1
    1. 1차 캐시 내에 내용이 없으므로 DB에서 데이터를 조회한다.
    2. 조회한 데이터의 PK(@Entity의 @Id)의 값을 키로, 데이터 전체(@Entity)를 1차 캐시에 저장한다.
  3. member2
    1. 1차 캐시에 데이터가 있으므로 1차 캐시 먼저 확인한다.
    2. 1차 캐시에 키가 100인 데이터가 존재하는지 확인한다.
    3. 데이터가 존재하므로 DB에 SQL를 실행해 확인하는 것이 아닌, 1차 캐시에서 데이터를 읽어온다.
String id = "100";
Member member1 = jpa.find(Member.class, id); // SQL 동작
Member member2 = jpa.find(Member.class, id); // 캐시

member1 == member2 // true

트랜잭션을 지원하는 쓰기 지연(버퍼의 개념)

영속성 컨텍스트에 쓰기 지연 SQL 저장소가 존재한다.

데이터의 변경(Insert, Update, Delete)의 경우 SQL만 작성하여 놓고 쓰기 지연 SQL 저장소에 SQL을 모아둔다.

트랜잭션을 커밋할 때 모아둔 SQL을 실행한다.

em.persist의 경우 영속화하여 영속성 컨텍스트에서 관리하는 상태로 변경하는 것이다.

transaction.begin(); // 트랜잭션 시작

em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
// 여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.

// 커밋하는 순간 데이테베이스에 INSERT SQL을 모아서 보낸다.
transaction.commit();

지연 로딩과 즉시 로딩

지연 로딩 : 객체가 실제 사용될 때 로딩

즉시 로딩 : JOIN SQL로 한번에 연관된 객체까지 미리 조회

// * 지연 로딩
Member member = memberDAO.find(memberId); // SELECT * FROM MEMBER
Team team = Member.getTeam();
String teamName = team.getName(); // SELECT * FROM TEAM
// * 즉시로딩
Member member = memberDAO.find(memberId); // SELECT A.*, B.* FROM MEMBER JOIN TEAM ...
Team team = member.getTeam();
String teamName = team.getName();

변경 감지

영속성 컨텍스트의 1차 캐시에 스냅샷이 존재한다.

스냅샷은 1차 캐시에 Entity가 등록될 때 같이 저장되고, 트랜잭션의 commit을 실행할 때 Entity와 스냅샷을 비교하여 변경을 감지한다.

데이터의 변경이 발생했다면 UPDATE SQL을 작성하여 쓰기 지연 SQL 저장소에 저장하고 저장되어 있던 SQL과 함께 DB에 전달되어 실행된다.

Member member = em.find(Member.class, 100L);
System.out.println("member.id : " + member.getId()); // 100
System.out.println("member.name : " + member.getName()); // A

member.setName("B");

tx.commit();

엔티티의 생명주기

비영속(new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태

Member member = new Member();
member.setId(100L);
member.setName("helloJPA");

영속(managed) : 영속성 컨텍스트에 관리되는 상태

em.persist(member);

준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태

em.detach(member);

삭제(removed) : 삭제된 상태

em.remove(member);

 

Reference

자바 ORM 표준 JPA 프로그래밍(인프런, 김영한)

'framework > jpa' 카테고리의 다른 글

[JPA] 엔티티 매핑 3  (0) 2023.04.23
[JPA] 엔티티 매핑 2  (0) 2023.04.09
[JPA] 엔티티 매핑 1  (0) 2023.04.08
[JPA] 기본 사용 방법  (0) 2023.04.07
[JPA] JPA 사용 전 객체지향 프로그래밍의 불편함  (0) 2023.04.07