JPA(Java Persistance API)

럼포 ㅣ 2024. 12. 17. 14:40

JPA란?

 

JAVA EE 표준 명세로, 객체와 관계형 데이터베이스 같의 매핑을 지원하는 ORM 기술.

인터페이스만을 제공하며 구현체가 필요

Hibernate, EclipseLink,OpenJPA 등의 구현체가 있으며, 일반적으로 Hibernate를 많이 씀


 

JPA 구성 요소

 

1. Entity

데이터베이스 테이블과 매핑되는 자바 클래스

@Entity 어노테이션으로 Entity 선언

import javax.persistence.*;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // Primary Key

    @Column(nullable = false)
    private String name;

    // Getters and Setters
}

 

객체와 관계형 데이터베이스는 구조 간 차이 때문에 완벽하게 대응이 되지 않는다. 이를 임피던스 불일치(Impedance Mismatch)라고 하는데, 도메인 객체를 바로 Entity로 매핑할 수도 있지만 임피던스 불일치 등을 이유로 별도의 매핑 클래스(Jpo)를 사용할 때도 있다. 즉 테이블의 컬럼을 가져올 때 그것과 매핑되는 클래스를 만든다는 얘기다. 

 

 

 

2. EntityManager

JPA의 핵심 인터페이스로 Entity를 관리하고 DB에 접근

Entity의 생명주기 (Persist, Merge, Remove, Detach) 를 관리

@PersistenceContext
private EntityManager entityManager;

public void saveUser(User user) {
    entityManager.persist(user); // 객체를 저장
}

public User getUser(Long id) {
    return entityManager.find(User.class, id); // 객체를 조회
}

 

 3. Persistence Context

JPA에서 Entity 객체를 저장하고 관리하는 메모리상의 작업 공간

Entity Manager에서 Persistence Context 관리

 

Persistence Context를 사용하는 이유?

  • 1차 캐시를 통한 성능 최적화

Persistence Context는 처음 쿼리 시 쿼리 결과를 메모리 상에 저장하는데, 중복된 쿼리 요청이 들어올 경우 추가적인 데이터베이스 접근 없이 자원을 절약할 수 있다.

  • User user1 = entityManager.find(User.class, 1L); // DB에서 조회 -> 1차 캐시에 저장 User user2 = entityManager.find(User.class, 1L); // 1차 캐시에서 조회 -> DB 접근 X

 

  • 변경 감지

Persistence Context는 Entity의 변경 사항을 자동으로 감지하므로 UPDATE SQL을 수동으로 작성하지 않아도 되어 생산성이 높아지고, 오류 발생 가능성이 줄어든다.

User user = entityManager.find(User.class, 1L);
user.setName("New Name"); // 영속성 컨텍스트가 변경 감지
entityManager.getTransaction().commit(); // 자동으로 UPDATE SQL 실행

 

  • 쓰기 지연

데이터베이쓰에 즉시 쿼리를 실행하지 않고 트랜잭션 커밋 시점에 한꺼번에 실행하는 것을 쓰기 지연(Write-Behind)라고 하며 여러 작업을 하나의 트랜잭션으로 묶어 처리하므로 데이터베이스 연결 비용이 줄어들고 성능을 최적화하는 효과를 얻을 수 있다.

entityManager.persist(user1); // INSERT 지연
entityManager.persist(user2); // INSERT 지연
entityManager.getTransaction().commit(); // INSERT 쿼리 한 번에 실행