[Spring JPA] JPA 개념과 예제

2025. 2. 13. 03:16·Spring

1. JPA란?

JPA(Java Persistence API)는 자바 애플리케이션에서 객체와 관계형 데이터베이스(RDB) 간의 매핑을 처리하는 ORM (Object-Relational Mapping) 기술의 표준 인터페이스이다.

 

JPA와 Hibernate의 관계

   - JPA: ORM을 위한 자바 표준 인터페이스로, 특정 구현체에 의존하지 않음

   - Hibernate: JPA의 대표적인 구현체

   - Spring Data JPA: JPA를 더 쉽게 사용할 수 있도록 추상화한 모듈

// JPA 표준 API
implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
// Hibernate (JPA의 대표적인 구현체)
implementation 'org.hibernate:hibernate-core:6.4.4.Final'

 


2. JPA의 주요 구성 요소

JPA의 핵심 개념을 이해하려면 EntityManagerFactory, EntityManager, 영속성 컨텍스트(Persistence Context) 개념을 파악해야 한다.

EntityManagerFactory

   - `EntityManager` 인스턴스를 생성하는 팩토리 클래스

   - 일반적으로 애플리케이션에서 단 하나만 존재하며, 이를 통해 여러 `EntityManager`를 생성

EntityManager

   - 트랜잭션 단위로 사용되며, 매 요청마다 새로운 인스턴스를 생성

   - 엔티티의 생명 주기를 관리하는 역할 수행

영속성 컨텍스트 (Persistence Context)

   - 엔티티 객체를 관리하는 환경

   - 트랜잭션 범위 내에서 엔티티를 저장하고 변경 사항을 추적함

   - 1차 캐시를 이용해 동일 트랜잭션 내에서 동일한 엔티티 조회 시 DB 조회 없이 기존 객체를 반환 (성능 최적화)

 

출처: 자바 ORM 표준 JPA 프로그래밍 - 기본편
출처: KihoonKim:Dev

 


3. JPA 설정 (persistence.xml)

JPA를 사용하려면 `persistence.xml` 설정이 필요하다.

 

▶ 파일 위치: `src/main/resources/META-INF/persistence.xml`

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             version="3.1">
    <persistence-unit name="UserPU" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.example.jpa.User</class>  <!-- 엔티티 클래스 등록 -->
        <properties>
            <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/exampledb"/>
            <property name="jakarta.persistence.jdbc.user" value="root"/>
            <property name="jakarta.persistence.jdbc.password" value="1234"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>
주요 설정
  1. `<persistence-unit>`: 데이터베이스 연결과 엔티티 관리를 위한 설정 그룹을 정의 (다중 데이터베이스 지원)
  2. `<provider>`: 구현체가 Hibernate
  3. `<class>`: 관리할 엔티티 클래스
  4. `<properties>`: JDBC 관련 설정
    • `hibernate.hbm2ddl.auto`옵션은 데이터베이스 테이블을 어떻게 관리할지 결정한다.
      • `create`: 매번 기존 테이블을 삭제 후 새롭게 생성(테스트 환경에서 추천)
      • `update`: 기존 스키마를 유지하면서 변경 사항만 반영(개발 환경)
      • `create-drop`: `create`와 동일하지만, 애플리케이션 종료 시 테이블을 삭제
      • `validate`: 엔티티와 DB 스키마가 일치하는지 검증 (운영 환경에서 추천)
    • `hibernate.dialect` (DBMS에 맞는 SQL 생성)
      • SQL 동적 생성, 데이터 타입 변환, 페이징 처리 (MySQL → LIMIT, Oracle → ROWNUM)

 


4. JPA 기본 예제

▶ 엔티티(Entity) 정의

package com.example.jpa;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity
@Table(name = "users")
@Getter @Setter
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
}
`@Entity`: JPA가 관리하는 엔티티임을 선언
`@Table(name = "users")`: DB 테이블명 지정
`@Id @GeneratedValue(strategy = GenerationType.IDENTITY)`: 기본 키 자동 생성

 

▶ EntityManager를 활용한 데이터 저장

package com.example.jpa;

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

public class UserRun {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("UserPU");
        EntityManager entityManager = emf.createEntityManager();

        // 아직 영속성 컨텍스트가 관리하지 않는 상태
        User user = new User();
        user.setName("kim");
        user.setEmail("kim@gmail.com");

        entityManager.getTransaction().begin(); // 트랜잭션 시작
        entityManager.persist(user);  // 영속성 컨텍스트에 저장 (이 시점에 INSERT SQL 실행X)
        entityManager.getTransaction().commit(); // 실제 DB 반영
    }
}
데이터베이스 작업 시 트랜잭션이 필요한 이유:
읽기(read) 작업은 기본적으로 트랜잭션 관리 없이 수행 가능
삽입(Insert), 수정(Update), 삭제(Delete) 작업은 명시적인 트랜잭션 처리가 필요

 


5. JPA의 엔티티 생명주기 (Entity Life Cycle)

JPA에서 엔티티는 영속성 컨텍스트에 의해 관리되며, 엔티티는 다음과 같은 4가지 주요 상태를 가진다.

엔티티의 주요 생명주기 상태
상태 설명
비영속 (New/Transient) 엔티티가 새로 생성되었지만, 아직 영속성 컨텍스트에는 관리되지 않는 상태
영속 (Managed) `persist()` 호출 후 영속성 컨텍스트에 저장되어 관리되는 상태
준영속 (Detached) `detach()`, `clear()`, `close()` 등의 메서드 호출로 영속성 컨텍스트에서 분리된 상태
삭제 (Removed) `remove()` 호출 후 데이터베이스에서 삭제될 예정인 상태

 

출처: 자바 ORM 표준 JPA 프로그래밍 - 기본편

생명주기 전환 메서드
메서드 설명
`persist(entity)` 엔티티를 영속 상태로 변경
`merge(entity)` 준영속(Detached) 상태의 엔티티를 다시 영속 상태로 복구
`remove(entity)` 엔티티를 삭제 상태로 변경
`detach(entity)` 엔티티를 영속성 컨텍스트에서 분리하여 변경 사항이 반영되지 않도록 함

 

merge() 활용 예제
package com.example.jpa;

import jakarta.persistence.*;

public class UserMergeExample {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("UserPU");
        EntityManager em = emf.createEntityManager();

        em.getTransaction().begin();
        
        // 기존 엔티티를 조회 후 준영속 상태로 변경
        User user = em.find(User.class, 1L);
        em.detach(user); // 준영속 상태
        
        user.setEmail("new.email@example.com"); // 변경 시도 (반영X)

        em.merge(user); // 준영속 엔티티를 다시 영속화하여 변경 반영

        em.getTransaction().commit();
        em.close();
    }
}

준영속 상태에서 변경된 엔티티를 다시 영속화하여 DB에 반영하는 데 사용된다.

 


6. 변경 감지(Dirty Checking)

JPA는 변경 감지(Dirty Checking) 기능을 통해 트랜잭션이 커밋될 때 수정된 엔티티만 UPDATE 쿼리를 실행한다.
엔티티를 조회한 후 setXXX()을 호출해 값을 변경해도 update SQL이 즉시 실행되지 않고, 트랜잭션이 종료될 때 변경 사항을 자동으로 감지하여 DB에 반영한다.

import jakarta.persistence.*;

public class UpdateExample {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("ExamplePU");
        EntityManager em = emf.createEntityManager();

        em.getTransaction().begin();

        // 기존 엔티티 조회
        User user = em.find(User.class, 1L);

        if (user != null) {
            user.setEmail("updated.email@example.com");  // 변경됨
        }

        // 트랜잭션을 커밋하면 변경된 사항이 자동으로 DB 반영됨
        em.getTransaction().commit();

        em.close();
        emf.close();
    }
}

 

  • Dirty Checking이 가능한 이유
    • JPA는 엔티티를 조회하는 시점에 초기 상태의 스냅샷을 생성
    • 트랜잭션 커밋 시점에 기존 스냅샷과 현재 엔티티 상태를 비교하여 변경된 필드만 UPDATE SQL 실행

출처: 자바 ORM 표준 JPA 프로그래밍 - 기본편

 


7. JPA의 지연 로딩 (Lazy Loading)

JPA는 연관된 엔티티를 즉시 로딩(Eager Loading) 또는 지연 로딩(Lazy Loading) 방식으로 가져올 수 있다.

즉시 로딩 (Eager Loading)

   - `@ManyToOne(fetch = FetchType.EAGER)`

   - 엔티티 조회 시 즉시 연관된 엔티티도 함께 로딩하는 방식

   - 단점: 필요하지 않은 데이터까지 불필요하게 로딩되어 성능 저하 발생 가능

 

지연 로딩 (Lazy Loading)

   - `@ManyToOne(fetch = FetchType.LAZY)`

   - 엔티티 조회 시 실제 데이터를 사용하는 시점에만 연관된 엔티티를 조회하는 방식

   - 장점: 필요한 경우에만 데이터를 로딩하여 성능 최적화 가능

 

▶ Lazy Loading 예제

@Entity
public class Order {
    @Id @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY) // 지연 로딩 설정
    private Customer customer;
}
  • Lazy Loading은 실제 연관 데이터를 사용하는 시점에만 쿼리를 실행하는 방식이다.
  • 이를 통해 불필요한 데이터 로드를 방지하고 성능을 최적화할 수 있다.
  • 단, 지연 로딩된 데이터를 트랜잭션 밖에서 호출하면 LazyInitializationException이 발생할 수 있다.

 


8. 결론

JPA는 객체 지향적인 방식으로 데이터베이스를 다룰 수 있도록 도와주며,
영속성 컨텍스트와 변경 감지를 활용해 성능을 최적화할 수 있다.
하지만 LazyInitializationException, N+1 문제와 같은 성능 이슈를 주의해야 하며,
이를 해결하기 위해 적절한 조회 전략(Fetch Join, DTO Projection)과
트랜잭션 관리를 신중하게 고려해야 한다.

 

'Spring' 카테고리의 다른 글

[Spring MVC] 요청 처리 과정과 동작 원리  (0) 2025.02.10
'Spring' 카테고리의 다른 글
  • [Spring MVC] 요청 처리 과정과 동작 원리
oniwon
oniwon
  • oniwon
    눙눙의 개발일지
    oniwon
  • 전체
    오늘
    어제
    • 분류 전체보기
      • Java
      • Spring
      • CS
      • Infra
      • Projects
      • F-Lab
      • Airflow
  • 인기 글

  • 블로그 메뉴

    • 홈
    • 개인정보처리방침 (Privacy Policy)
    • 블로그 소개 (About)
  • 최근 글

  • 태그

    자바 내부 동작
    Flab 3주차 후기
    Flab추천인코드
    F-Lab
    SSE
    Flab 멘토링
    Flab멘토링
    Java
    자바백엔드
    병렬 처리
    에프랩멘토링
    FLAB
    비동기 처리
    tls
    Flab커넥터스
    redis
    동시성
    Flab 추천인코드
    https
    DAG
    Airflow
    에프랩
    자바 다형성
    네트워크
    자바면접
    inconcert
    JVM
    dns
    커넥터스2385
    Flab후기
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.1
oniwon
[Spring JPA] JPA 개념과 예제
상단으로

티스토리툴바